blob: 9e9134c961969bd7719397d3e30d9c18e0e7fd70 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2005, 2016 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
* Sopot Cela - Bug 466829
*******************************************************************************/
package org.eclipse.help.internal.search;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import org.eclipse.core.runtime.FileLocator;
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.help.internal.base.HelpBasePlugin;
import org.eclipse.help.internal.base.util.ProxyUtil;
import org.eclipse.help.internal.util.ResourceLocator;
import org.osgi.framework.Bundle;
public class PluginIndex {
private static final String COMPLETE_FILENAME = "indexed_complete"; //$NON-NLS-1$
private String pluginId;
/**
* index path as defined in plugin.xml, e.g. "index"
*/
private String path;
private SearchIndex targetIndex;
/**
* path prefixes where index is found e.g. "", "nl/en/US", "ws/gtk"
*/
private List<String> indexIDs;
/**
* resolved directory paths (Strings) corresponding to indexes at given
* prefixes, e.g. //d/eclipse/...../os/linux/index,
*/
private List<String> resolvedPaths;
public PluginIndex(String pluginId, String path, SearchIndex targetIndex) {
super();
this.pluginId = pluginId;
this.path = path;
this.targetIndex = targetIndex;
}
private void resolve() {
if (indexIDs != null) {
// resolved
return;
}
indexIDs = new ArrayList<>();
resolvedPaths = new ArrayList<>();
Bundle bundle = Platform.getBundle(pluginId);
if (bundle == null) {
return;
}
boolean found = false;
ArrayList<String> availablePrefixes = ResourceLocator.getPathPrefix(targetIndex
.getLocale());
for (int i = 0; i < availablePrefixes.size(); i++) {
String prefix = availablePrefixes.get(i);
IPath prefixedPath = new Path(prefix + path);
// find index at this directory in plugin or fragments
URL url = FileLocator.find(bundle, prefixedPath, null);
if (url == null) {
continue;
}
found = true;
if (!isCompatible(bundle, prefixedPath)) {
continue;
}
URL resolved;
try {
resolved = FileLocator.resolve(url);
} catch (IOException ioe) {
HelpBasePlugin.logError("Help index directory at " //$NON-NLS-1$
+ prefixedPath + " for plugin " //$NON-NLS-1$
+ bundle.getSymbolicName() + " cannot be resolved.", //$NON-NLS-1$
ioe);
continue;
}
if ("file".equals(resolved.getProtocol())) { //$NON-NLS-1$
indexIDs.add(getIndexId(prefix));
resolvedPaths.add(resolved.getFile());
if (isComplete(bundle, prefixedPath)) {
// don't process default language index
break;
}
} else {
try {
// extract index from jarred bundles
URL localURL = FileLocator.toFileURL(url);
if ("file".equals(localURL.getProtocol())) { //$NON-NLS-1$
indexIDs.add(getIndexId(prefix));
resolvedPaths.add(localURL.getFile());
if (isComplete(bundle, prefixedPath)) {
// don't process default language index
break;
}
}
} catch (IOException ioe) {
HelpBasePlugin.logError(
"Help index directory at " + prefixedPath //$NON-NLS-1$
+ " for plugin " + bundle.getSymbolicName() //$NON-NLS-1$
+ " cannot be resolved.", ioe); //$NON-NLS-1$
continue;
}
}
}
if (!found) {
HelpBasePlugin.logError(
"Help index declared, but missing for plugin " //$NON-NLS-1$
+ getPluginId() + ".", null); //$NON-NLS-1$
}
}
public boolean isCompatible(Bundle bundle, IPath prefixedPath) {
URL url = FileLocator.find(bundle, prefixedPath.append(SearchIndex.DEPENDENCIES_VERSION_FILENAME), null);
if (url == null) {
HelpBasePlugin.logError(
prefixedPath.append(SearchIndex.DEPENDENCIES_VERSION_FILENAME) + " file missing from help index \"" //$NON-NLS-1$
+ path + "\" of plugin " + getPluginId(), //$NON-NLS-1$
null);
return false;
}
try (InputStream in = ProxyUtil.getStream(url)) {
Properties prop = new Properties();
prop.load(in);
String lucene = prop
.getProperty(SearchIndex.DEPENDENCIES_KEY_LUCENE);
String analyzer = prop
.getProperty(SearchIndex.DEPENDENCIES_KEY_ANALYZER);
if (!targetIndex.isLuceneCompatible(lucene) || !targetIndex.isAnalyzerCompatible(analyzer)) {
String message = "Unable to consume Lucene index from bundle '" + bundle.toString() //$NON-NLS-1$
+ "'. The index should be rebuilt with Lucene 6.1."; //$NON-NLS-1$
Status warningStatus = new Status(IStatus.WARNING, HelpBasePlugin.PLUGIN_ID, IStatus.OK, message, null);
HelpBasePlugin.logStatus(warningStatus);
return false;
}
} catch (MalformedURLException mue) {
return false;
} catch (IOException ioe) {
HelpBasePlugin.logError(
"IOException accessing prebuilt index.", ioe); //$NON-NLS-1$
}
return true;
}
private boolean isComplete(Bundle bundle, IPath prefixedPath) {
URL url = FileLocator.find(bundle, prefixedPath.append(COMPLETE_FILENAME), null);
return url != null;
}
/**
* Creates id of prebuilt index
*
* @param prefix
* index directory prefix, e.g. "", "ws/gtk"
* @return indexId string, e.g. "/", "/ws/gtk"
*/
private String getIndexId(String prefix) {
if (prefix.length() == 0) {
// root
return "/"; //$NON-NLS-1$
}
return "/" + prefix.substring(0, prefix.length() - 1); //$NON-NLS-1$
}
@Override
public boolean equals(Object obj) {
if ( !(obj instanceof PluginIndex) ) {
return false;
}
PluginIndex index = (PluginIndex) obj;
return pluginId.equals(index.pluginId) && path.equals(index.path);
}
@Override
public int hashCode() {
return pluginId.hashCode() + path.hashCode();
}
@Override
public String toString() {
StringBuffer ret = new StringBuffer(pluginId);
ret.append(":"); //$NON-NLS-1$
ret.append(path);
ret.append("="); //$NON-NLS-1$
if (indexIDs == null) {
ret.append("unresolved"); //$NON-NLS-1$
} else {
for (int i = 0; i < indexIDs.size(); i++) {
ret.append(indexIDs.get(i));
ret.append("@"); //$NON-NLS-1$
ret.append(resolvedPaths.get(i));
}
}
return ret.toString();
}
public List<String> getIDs() {
resolve();
return indexIDs;
}
/**
* @return list of paths (string) to an index directory. Paths are ordered
* from
*/
public List<String> getPaths() {
resolve();
return resolvedPaths;
}
public String getPluginId() {
return pluginId;
}
}