/* ******************************************************************************
* Copyright (c) 2006-2012 XMind Ltd. and others.
*
* This file is a part of XMind 3. XMind releases 3 and
* above are dual-licensed under the Eclipse Public License (EPL),
* which is available at http://www.eclipse.org/legal/epl-v10.html
* and the GNU Lesser General Public License (LGPL),
* which is available at http://www.gnu.org/licenses/lgpl.html
* See http://www.xmind.net/license.html for details.
*
* Contributors:
* XMind Ltd. - initial API and implementation
*******************************************************************************/
package org.xmind.ui.internal.protocols;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.SafeRunner;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.util.SafeRunnable;
import org.eclipse.osgi.util.NLS;
import org.eclipse.ui.internal.registry.RegistryReader;
import org.xmind.core.util.HyperlinkUtils;
import org.xmind.ui.browser.BrowserSupport;
import org.xmind.ui.internal.MindMapMessages;
import org.xmind.ui.internal.browser.BrowserUtil;
import org.xmind.ui.internal.mindmap.TopicContext;
import org.xmind.ui.mindmap.IMindMapImages;
import org.xmind.ui.mindmap.IProtocol;
import org.xmind.ui.mindmap.IProtocolDescriptor;
import org.xmind.ui.mindmap.IProtocolManager;
import org.xmind.ui.mindmap.ITopicPart;
import org.xmind.ui.mindmap.MindMapUI;
import org.xmind.ui.util.Logger;
public class ProtocolManager extends RegistryReader
implements IProtocolManager {
private static String DEFAULT_BROWSER_ID = "org.xmind.ui.defaultProtocol.browser"; //$NON-NLS-1$
private static class DefaultOpenURLAction extends Action {
private String url;
public DefaultOpenURLAction(String url) {
super(MindMapMessages.OpenHyperlink_text,
MindMapUI.getImages().get(IMindMapImages.HYPERLINK, true));
this.url = url;
setDisabledImageDescriptor(
MindMapUI.getImages().get(IMindMapImages.HYPERLINK, false));
setToolTipText(url);
}
public void run() {
SafeRunner.run(new SafeRunnable() {
public void run() throws Exception {
String theURL = url;
try {
URI uri = new URI(theURL);
String host = uri.getHost();
if (host != null && host.endsWith(".xmind.net")) { //$NON-NLS-1$
theURL = BrowserUtil.makeRedirectURL(theURL);
}
} catch (Exception ignored) {
}
BrowserSupport.getInstance()
.createBrowser(DEFAULT_BROWSER_ID).openURL(theURL);
}
});
}
}
protected static class DefaultProtocol implements IProtocol {
public String getProtocolName() {
return null;
}
public IAction createOpenHyperlinkAction(Object source,
final String uri) {
return new DefaultOpenURLAction(uri);
}
public boolean isHyperlinkModifiable(Object source, String uri) {
return true;
}
}
private IProtocol defaultProtocol = null;
private List<ProtocolDescriptor> protocolDescriptors = null;
private Map<String, IProtocol> protocols = null;
public ProtocolManager() {
}
private List<ProtocolDescriptor> getProtocolDescriptors() {
ensureLoaded();
return protocolDescriptors;
}
private void ensureLoaded() {
if (protocolDescriptors != null)
return;
lazyLoad();
if (protocolDescriptors == null)
protocolDescriptors = Collections.emptyList();
}
private void lazyLoad() {
readRegistry(Platform.getExtensionRegistry(), MindMapUI.PLUGIN_ID,
"protocols"); //$NON-NLS-1$
}
protected boolean readElement(IConfigurationElement element) {
String name = element.getName();
if ("protocol".equals(name)) { //$NON-NLS-1$
readProtocolDescriptor(element);
return true;
}
return false;
}
private void readProtocolDescriptor(IConfigurationElement element) {
try {
registerProtocolDescriptor(new ProtocolDescriptor(element));
} catch (CoreException e) {
Logger.log(e);
}
}
private void registerProtocolDescriptor(
ProtocolDescriptor protocolDescriptor) {
if (protocolDescriptors == null)
protocolDescriptors = new ArrayList<ProtocolDescriptor>();
protocolDescriptors.add(protocolDescriptor);
}
private IProtocol getDefaultProtocol() {
if (defaultProtocol == null)
defaultProtocol = createDefaultProtocol();
return defaultProtocol;
}
private IProtocol createDefaultProtocol() {
return new DefaultProtocol();
}
public IProtocolDescriptor findProtocolDescriptor(String uri) {
String name = HyperlinkUtils.getProtocolName(uri);
if (name != null) {
for (ProtocolDescriptor p : getProtocolDescriptors()) {
if (p.hasProtocolName(name)) {
return p;
}
}
}
return null;
}
public IProtocol findProtocol(String uri) {
return getProtocol(findProtocolDescriptor(uri));
}
private IProtocol getProtocol(IProtocolDescriptor desc) {
if (desc != null) {
IProtocol p = getCreatedProtocol((ProtocolDescriptor) desc);
if (p != null)
return p;
}
return getDefaultProtocol();
}
private IProtocol getCreatedProtocol(IProtocolDescriptor desc) {
if (protocols == null)
protocols = new HashMap<String, IProtocol>();
String id = desc.getId();
IProtocol protocol = getExistingProtocol(id);
if (protocol == null) {
protocol = createProtocol((ProtocolDescriptor) desc);
registerProtocol(id, protocol);
}
return protocol;
}
private IProtocol registerProtocol(String id, IProtocol protocol) {
return protocols.put(id, protocol);
}
private IProtocol getExistingProtocol(String id) {
return protocols.get(id);
}
private IProtocol createProtocol(ProtocolDescriptor p) {
try {
return p.createProtocol();
} catch (CoreException e) {
Logger.log(e, "Failed to create protocol: " + p.getId()); //$NON-NLS-1$
}
return getDefaultProtocol();
}
public IAction createOpenHyperlinkAction(Object context, String uri) {
if (context instanceof ITopicPart) {
context = new TopicContext((ITopicPart) context);
}
IProtocolDescriptor desc = findProtocolDescriptor(uri);
return adaptAction(
getProtocol(desc).createOpenHyperlinkAction(context, uri), desc,
uri);
}
private IAction adaptAction(IAction action, IProtocolDescriptor desc,
String uri) {
if (action == null)
return null;
if (action.getText() == null) {
String text;
if (desc == null) {
text = MindMapMessages.OpenHyperlink_text;
} else {
text = NLS.bind(
MindMapMessages.ProtocolManager_OpenHyperlink_pattern,
desc.getName());
}
action.setText(text);
}
if (action.getImageDescriptor() == null) {
action.setImageDescriptor(
MindMapUI.getImages().get(IMindMapImages.HYPERLINK, true));
}
if (action.getToolTipText() == null) {
action.setToolTipText(uri);
}
return action;
}
public boolean isHyperlinkModifiable(Object context, String uri) {
if (context instanceof ITopicPart) {
context = new TopicContext((ITopicPart) context);
}
return findProtocol(uri).isHyperlinkModifiable(context, uri);
}
}