package org.xmind.ui.internal.protocols;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URI;
import org.eclipse.core.runtime.SafeRunner;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.util.SafeRunnable;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Display;
import org.xmind.core.Core;
import org.xmind.core.IAdaptable;
import org.xmind.core.ITopic;
import org.xmind.core.event.ICoreEventSource;
import org.xmind.core.util.FileUtils;
import org.xmind.gef.image.ImageExportUtils;
import org.xmind.ui.browser.BrowserSupport;
import org.xmind.ui.internal.MindMapMessages;
import org.xmind.ui.internal.browser.BrowserUtil;
import org.xmind.ui.io.WebImageManager;
import org.xmind.ui.io.WebImageManager.WebImageCallback;
import org.xmind.ui.mindmap.IMindMapImages;
import org.xmind.ui.mindmap.IProtocol;
import org.xmind.ui.mindmap.MindMapUI;
import org.xmind.ui.resources.ImageUtils;
import org.xmind.ui.util.MindMapUtils;
public class WebProtocol implements IProtocol {
private static interface Callback {
void handleWith(ImageDescriptor icon);
}
public static final String WEB_ICON_EVENT_TYPE = "webIcon"; //$NON-NLS-1$
private static String DEFAULT_BROWSER_ID = "org.xmind.ui.defaultProtocol.browser"; //$NON-NLS-1$
private static final String PATH_FAVICONS = "favicons/"; //$NON-NLS-1$
private static class OpenURLAction extends Action {
private String url;
public OpenURLAction(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);
if ("www.xmind.net".equals(uri.getHost())) { //$NON-NLS-1$
theURL = BrowserUtil.makeRedirectURL(theURL);
}
} catch (Exception ignored) {
}
BrowserSupport.getInstance()
.createBrowser(DEFAULT_BROWSER_ID).openURL(theURL);
}
});
}
}
public IAction createOpenHyperlinkAction(final Object context,
final String url) {
final IAction action = new OpenURLAction(url);
ImageDescriptor image = getWebIcon(url, new Callback() {
public void handleWith(final ImageDescriptor icon) {
if (icon == null) {
return;
}
Display.getDefault().asyncExec(new Runnable() {
public void run() {
ImageDescriptor oldImage = action.getImageDescriptor();
action.setImageDescriptor(icon);
ITopic topic = null;
if (context instanceof ITopic) {
topic = (ITopic) context;
} else if (context instanceof IAdaptable) {
topic = (ITopic) ((IAdaptable) context)
.getAdapter(ITopic.class);
}
if (topic != null) {
ICoreEventSource source = topic
.getAdapter(ICoreEventSource.class);
if (source != null) {
source.getCoreEventSupport()
.dispatchValueChange(source,
WebProtocol.WEB_ICON_EVENT_TYPE,
oldImage, icon);
}
}
}
});
}
});
if (image != null) {
action.setImageDescriptor(image);
}
return action;
}
private ImageDescriptor getWebIcon(String url, final Callback callback) {
final String iconUrl = getWebIconUrl(url);
if (iconUrl == null) {
return null;
}
final String key = "org.xmind.ui.webIcon(" + iconUrl + ")"; //$NON-NLS-1$ //$NON-NLS-2$
ImageDescriptor image = ImageUtils.getDescriptor(key);
if (image != null) {
return image;
}
image = getFaviconFromFile(iconUrl);
if (image != null) {
ImageUtils.putImageDescriptor(key, image);
return image;
}
WebImageManager.getInstance().requestWebImage(iconUrl,
new WebImageCallback() {
public void handleWith(String imagePath) {
if (imagePath == null
|| !new File(imagePath).exists()) {
return;
}
String newPath = saveFaviconToFile(iconUrl, imagePath);
if (newPath == null || !new File(newPath).exists()) {
return;
}
ImageDescriptor image = null;
try {
image = ImageDescriptor.createFromURL(
new File(newPath).toURI().toURL());
} catch (MalformedURLException e) {
e.printStackTrace();
}
if (image == null) {
return;
}
ImageUtils.putImageDescriptor(key, image);
if (callback != null) {
callback.handleWith(image);
}
}
});
return null;
}
private String getWebIconUrl(String url) {
if (url == null) {
return null;
}
int domainEnd = -1;
if (url.contains("://")) { //$NON-NLS-1$
int start = url.indexOf("://") + "://".length(); //$NON-NLS-1$ //$NON-NLS-2$
domainEnd = url.indexOf("/", start); //$NON-NLS-1$
} else {
domainEnd = url.indexOf("/"); //$NON-NLS-1$
}
String domain = url.substring(0,
domainEnd == -1 ? url.length() : domainEnd);
return domain + "/favicon.ico"; //$NON-NLS-1$
}
private ImageDescriptor getFaviconFromFile(String key) {
String fileName = getFileName(key);
String path = Core.getWorkspace()
.getAbsolutePath(PATH_FAVICONS + fileName);
if (path == null) {
return null;
}
File file = new File(path);
if (file.exists()) {
long lastModified = file.lastModified();
long currentTime = System.currentTimeMillis();
//the validity of image file is 30 days.
if ((currentTime - lastModified) / (24 * 3600 * 1000) > 30) {
file.delete();
} else {
try {
return ImageDescriptor
.createFromURL(new File(path).toURI().toURL());
} catch (MalformedURLException e) {
e.printStackTrace();
}
}
}
return null;
}
private String saveFaviconToFile(String key, String tempImagePath) {
if (tempImagePath == null) {
return null;
}
String fileName = getFileName(key);
String path = Core.getWorkspace()
.getAbsolutePath(PATH_FAVICONS + fileName);
if (path == null) {
return null;
}
File file = new File(path);
if (file.exists()) {
return path;
}
Image image = null;
try {
image = new Image(Display.getCurrent(), tempImagePath);
} catch (Exception e) {
return null;
}
Image image1x = ImageUtils.createScaledImage(image, 16, 16);
Image image2x = ImageUtils.createScaledImage(image, 32, 32);
FileUtils.ensureFileParent(file);
FileOutputStream outputStream = null;
FileOutputStream outputStream2x = null;
try {
//get @1x
File file1x = new File(path);
file1x.createNewFile();
outputStream = new FileOutputStream(file1x);
ImageExportUtils.saveImage(image1x, outputStream, SWT.IMAGE_PNG);
//get @2x
String path2x = Core.getWorkspace()
.getAbsolutePath(PATH_FAVICONS + get2xFileName(key));
File file2x = new File(path2x);
file2x.createNewFile();
outputStream2x = new FileOutputStream(file2x);
ImageExportUtils.saveImage(image2x, outputStream2x, SWT.IMAGE_PNG);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
outputStream.close();
outputStream2x.close();
} catch (IOException e) {
e.printStackTrace();
}
new File(tempImagePath).delete();
image.dispose();
image1x.dispose();
image2x.dispose();
}
return path;
}
private String getFileName(String key) {
if (key == null) {
return null;
}
key = key.substring(0, key.lastIndexOf(".ico")); //$NON-NLS-1$
key = key.replace("://", "-"); //$NON-NLS-1$ //$NON-NLS-2$
key = key.replace(".", "-"); //$NON-NLS-1$ //$NON-NLS-2$
key = key.replace("/", "-"); //$NON-NLS-1$ //$NON-NLS-2$
key += ".png"; //$NON-NLS-1$
key = MindMapUtils.trimFileName(key);
return key;
}
private String get2xFileName(String key) {
String fileName = getFileName(key);
if (fileName != null) {
fileName = fileName.substring(0, fileName.length() - 4) + "@2x" //$NON-NLS-1$
+ fileName.substring(fileName.length() - 4);
}
return fileName;
}
public boolean isHyperlinkModifiable(Object source, String uri) {
return true;
}
}