⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xrenderersupport.java

📁 XBrowser是一个完全免费并且开源的Web浏览器
💻 JAVA
字号:
/****************************************************************
*              XBrowser  -  eXtended web Browser                *
*                                                               *
*           Copyright (c) 2000-2001  Armond Avanes              *
*     Refer to ReadMe & License files for more information      *
*                                                               *
*                                                               *
*                 By: Uladzimir V. Kavalchuk                    *
*               Uladzimir_Kavalchuk@ep.minsk.by                 *
*               http://xbrowser.sourceforge.net/                *
*****************************************************************/
package xbrowser.renderer.custom;

import java.net.*;
import java.io.*;
import java.util.*;
import java.text.*;
import javax.swing.text.html.*;
import javax.swing.text.*;
import java.lang.reflect.*;

import xbrowser.renderer.*;
import xbrowser.cookie.*;

public final class XRendererSupport {

	public static void setContext(XRendererContext cntx)
	{
		context = cntx;
	}

	public static XRendererContext getContext()
	{
		return context;
	}

	/** This is Workaround for JDK bug on setIfModified(), up to merlin-beta. */
	public static void setIfModified( URLConnection conn, long lastMod) {
        Date date = new Date(lastMod);
        SimpleDateFormat df = new SimpleDateFormat(
            "EEE, dd MMM yyyy HH:mm:ss 'GMT'", Locale.ENGLISH);
        df.setTimeZone(TimeZone.getTimeZone("GMT"));
        conn.setRequestProperty( "If-Modified-Since", df.format(date));
        // Next line: Does not work! Sends in CLIENT locale!
        // conn.setIfModifiedSince( lastMod); -- open after merlin
	}

	public static boolean isCacheable( HttpURLConnection c, int response) {
		long expiration = c.getExpiration();
		long now = System.currentTimeMillis();
		boolean ok = ( response >= HttpURLConnection.HTTP_OK &&
				    response < HttpURLConnection.HTTP_MOVED_PERM) &&
					( c.getHeaderField( "Expires") == null || expiration > now) &&
					( ! "no-cache".equals( c.getHeaderField( "Cache-Control")) &&
					  ! "no-cache".equals( c.getHeaderField( "Pragma")) &&
					  c.getLastModified() < now
					);
		return ok;
	}

	/** Set the cookies */
	public static void setCookies(URL page, URLConnection conn)
	{
	Iterator cookies = getContext().getCookieManager().getApplicableCookies(page);
	String sCookie = null;

		while( cookies.hasNext() )
		{
		XCookie cookie = (XCookie)cookies.next();

		    if( sCookie == null)
				sCookie += cookie.toSendString();
			else
				sCookie += "; " + cookie.toSendString();

		    getContext().getLogger().message(_this, "Set cookie: " + cookie);
		}

		if( sCookie != null)
		    conn.setRequestProperty("Cookie", sCookie);
	}

	/** Storing cookies from server */
	public static void getCookies(URL page, URLConnection conn)
	{
	int i = 0;
		do {
	       String fieldName = conn.getHeaderFieldKey( i);
		   String cookie_field = conn.getHeaderField( i);
		   if( fieldName == null && cookie_field == null)
			   break;
		   if( fieldName != null && fieldName.equalsIgnoreCase( "Set-Cookie")) {

				if( cookie_field!=null )
				{
					getContext().getLogger().message(_this, "Got cookie: "+cookie_field);
					getContext().getCookieManager().setCookies(page, cookie_field);
				}
			}
		   i++;
		} while( true);
	}

    /** When saving, images/applets can be saved along.
	 *  @param doc The HTMLDocument which will be changed to refer to local parts.
	 *  @param dir Directory to save all images relative to.
	 *  @param mode Defines how to map images src url to file name.
	 */
    public static void makeDocLocal(HTMLDocument doc, String dir, int mode) throws IOException {
        ElementIterator i = new ElementIterator(doc);
        Element el;
        SavingCache cache = new SavingCache(doc);

        while( (el = i.next()) != null){
            HTML.Tag eltag = (HTML.Tag) el.getAttributes().getAttribute(StyleConstants.NameAttribute);
            if( HTML.Tag.IMG.equals(eltag) ) {
				makeImgLocal( doc, dir, cache, el);
            }
        }
    }

	private static void makeImgLocal(HTMLDocument doc, String dir, SavingCache cache,
		          Element el) throws IOException {

		String src = (String) el.getAttributes().getAttribute(HTML.Attribute.SRC);
		if( src == null) {
			getContext().getLogger().warning(_this, "SRC not found!");
			return;
		}
		long saveElapsed = 0;

		String newsrc = cache.get(src);
		if( newsrc == null ) {
			// NEED to Make element local
			File imageDir = new File( dir );
			newsrc = getLocalImagePath(src, imageDir);

			boolean saved = false;
			if( ! src.toLowerCase().startsWith( "file:")) {
				try{
				    URL imgURL = new URL( doc.getBase(), src);
					String url = imgURL.toString();
					if( getContext().getCacheManager().isCached( url)) {
						File cacheFile = getContext().getCacheManager().getFileToCache( url);
						long now = System.currentTimeMillis();
						copyFile( cacheFile, newsrc);
						long elapsed = System.currentTimeMillis() - now;
						saveElapsed += elapsed;
						saved = true;
					} else {
					  getContext().getLogger().error(_this, "Image is not cached???");
					}
				} catch( MalformedURLException mfe) {
					getContext().getLogger().error(_this, "Not saved because of Malformed: " + src);
				}
			}
			newsrc = newsrc.replace('\\', '/'); // Dont understand otherwise!
			if( ! saved) { // src is file:// or something failed!
				saveComponentFile(doc.getBase(), src, newsrc);
			}
			newsrc = "file:///" + newsrc;
			cache.put(src, newsrc);
        } else {
			//getContext().getLogger().message(_this, "Hit from cache!");
        }

		String newimg = changeImgSrc(el, newsrc);
        // getContext().getLogger().message(_this, src + " changed to " + newimg);
		try {
			setOuterHTML(doc, el, newimg);
		} catch( BadLocationException ex) {
			getContext().getLogger().error(_this, ex);
		}
	}

	/* Given IMG tag, will set its src to <code>newsrc</code> parameter given.  */
    public static String changeImgSrc(Element img, String newsrc) {
        String result = "<IMG ";
        AttributeSet as = img.getAttributes();
        Enumeration attr = as.getAttributeNames();
        while( attr.hasMoreElements()) {
            Object cur = attr.nextElement();
            Object value;
            if( cur.equals(StyleConstants.NameAttribute) )
                continue;
            if( ! cur.equals(HTML.Attribute.SRC) ) {
                value = as.getAttribute(cur);
            } else value = newsrc;
            result += cur + "=\"" + value + "\" ";
        }
        result += ">";
        return result;
    }

    /** Strategies to map Inet file name to local file name.
     *  Currently local file name is "<UNIQ_NUM>.<ext from src>".
     *  Requires that src is not <code>null</code>.
     */
    private static String getLocalImagePath(String src, File dir) {
        int last_dot = src.lastIndexOf('.');
        String ext = last_dot > 0 ? src.substring(last_dot) : "";
        if( ext.indexOf('?') > 0)
            ext = ".gif";

        File local_file = null;

        try { // XBL -- XBrowser Local file.
            local_file = File.createTempFile("XBL", ext, dir);
        } catch( IOException ex) {
			getContext().getLogger().error(_this, "Attempt failed: " + src);
			getContext().getLogger().error(_this, ex);

			local_file = new File(dir, "XB_Bad."+ext);
        }

        return local_file.getAbsolutePath();
    }

	private static void copyFile( File from, String to) throws IOException {
	    FileInputStream fis = new FileInputStream( from);
		FileOutputStream fos = new FileOutputStream( to);
		copyStreams( fis, fos, 0);
	}

	/** @deprecated Because does not use cache facilities. */
    private static void saveComponentFile(URL base_url, String link_src, String new_src)
            throws MalformedURLException, IOException   {
		getContext().getLogger().message( _this, "BAD: saveComponent()! " + link_src);
        URL itemUrl = new URL(base_url, link_src);
        URLConnection conn = (URLConnection) itemUrl.openConnection();
        InputStream is = conn.getInputStream();
        FileOutputStream fos = new FileOutputStream(new_src);
        copyStreams(is, fos, 0);
    }

	/** Utility method to copy whole content of streams. */
    public static void copyStreams(InputStream is, OutputStream fos, int size)
                       throws IOException {
        int thesize = size > 0 ? size : 4096;
        byte []buffer = new byte[ thesize];
        try {
            int actual, total = 0;
            do {
                actual = is.read(buffer, 0, thesize);
                if( actual <= 0)
                    break;
                total += actual;

                fos.write(buffer, 0, actual);
            } while(true);
        } finally {
            fos.close();
            is.close();
        }
    }

	public static void setOuterHTML(HTMLDocument doc, Element elem, String html_text) throws BadLocationException, IOException
	{
		try
		{
			invokeMethod(doc, "setOuterHTML", new Object[]{elem, html_text});
		}
		catch( BadLocationException e )
		{
			throw e;
		}
		catch( IOException e )
		{
			throw e;
		}
		catch( Exception e )
		{
			getContext().getLogger().error(_this, e);
		}
	}

	public static void insertAfterEnd(HTMLDocument doc, Element elem, String html_text) throws BadLocationException, IOException
	{
		try
		{
			invokeMethod(doc, "insertAfterEnd", new Object[]{elem, html_text});
		}
		catch( BadLocationException e )
		{
			throw e;
		}
		catch( IOException e )
		{
			throw e;
		}
		catch( Exception e )
		{
			getContext().getLogger().error(_this, e);
		}
	}

	public static void addStyleSheet(StyleSheet ss, StyleSheet ss_param)
	{
		try
		{
			invokeMethod(ss, "addStyleSheet", new Object[]{ss_param});
		}
		catch( Exception e )
		{
			getContext().getLogger().error(_this, e);
		}
	}

	public static void setParser(HTMLDocument doc, HTMLEditorKit.Parser parser)
	{
		try
		{
			invokeMethod(doc, "setParser", new Class[]{HTMLEditorKit.Parser.class}, new Object[]{parser});
		}
		catch( Exception e )
		{
			getContext().getLogger().error(_this, e);
		}
	}

	private static Object invokeMethod(Object method_owner, String method_name, Object[] method_params) throws Exception
	{
	Class[] params_classes = new Class[method_params.length];

		for( int i=0; i<method_params.length; i++ )
			params_classes[i] = method_params[i].getClass();

		return invokeMethod(method_owner, method_name, params_classes, method_params);
	}

	private static Object invokeMethod(Object method_owner, String method_name, Class[] param_types, Object[] method_params) throws Exception
	{
	Method method;

		try
		{
			method = method_owner.getClass().getMethod(method_name, param_types);
			return method.invoke(method_owner, method_params);
		}
		catch( NoSuchMethodException e )
		{
			getContext().getLogger().warning(_this, "'"+method_name+"' method not found in '"+method_owner.getClass().getName()+"' to invoke!!");
			getContext().getLogger().error(_this, e);
		}
		catch( SecurityException e )
		{
			getContext().getLogger().error(_this, e);
		}
		catch( IllegalAccessException e )
		{
			getContext().getLogger().error(_this, e);
		}
		catch( IllegalArgumentException e )
		{
			getContext().getLogger().error(_this, e);
		}
		catch( InvocationTargetException e )
		{
			getContext().getLogger().error(_this, e);
		}

		return null;
	}

    static class SavingCache {
        java.util.Map cache;
        Document document;

        public SavingCache(Document doc) {
            document = doc;
            Object objCache = doc.getProperty(SAVE_CACHE);
            // Should be persistent to avoid re-saving items for document given.
            if( (objCache==null) || !(objCache instanceof java.util.Map) ) {
                cache = new HashMap();
                doc.putProperty(SAVE_CACHE, cache);
            } else { // Or should we purge this?
                cache = (java.util.Map) objCache;
            }
        }

        public String get(String key) {
            return (String) cache.get(key);
        } // get

        public void put(String key, String value) {
            cache.put(key, value);
        } // get
    } // class SavingCache

	/* Asynchronous save (usually to cache). */
    public static class SavingThread extends Thread {
        public SavingThread( URL url, File cacheFile, List owner) {
		    setName( "Saving image " + url);
			setPriority( Thread.MIN_PRIORITY);
            this.url = url;
            this.cacheFile = cacheFile;
			this.owner = owner;
        }

        public void run() {
		    boolean ok = true;
            try {
				getContext().getLogger().message( this, "Started saving: " + url + " to " + cacheFile.getName());
				URLConnection conn = (URLConnection) url.openConnection();
				/** @todo: Query If-Modified-Since... */
				InputStream is = conn.getInputStream();
				String contentType = conn.getContentType();
				if( contentType != null)
					getContext().getCacheManager().setContentType( url.toString(), contentType);

				FileOutputStream fos = new FileOutputStream( cacheFile);
				copyStreams(is, fos, 0);
            } catch( IOException ioe) {
                getContext().getLogger().error( this, ioe);
				getContext().getCacheManager().removeFromCache( url.toString());
				ok = false;
            }
			if( owner != null)
				owner.remove( this);
			getContext().getLogger().message( this, "Saving: " + url + (ok?" complete!":" aborted."));
        }

	// Attributes:
        URL url;
        File cacheFile;
		List owner;
    } // class SavingThread

	public static class XInputSave {
		public XInputSave( File file) {
		    this.file = file;
			isFileBased = true;
		}

		public XInputSave() {
		    bos = new ByteArrayOutputStream();
		    isFileBased = false;
		}

		public InputStream getSavingStream( InputStream is) {
		    if( isFileBased)
				return is;
				// throw new IllegalAccessException( "SavingStream for file disabled!");

			XTeeInputStream newer = new XTeeInputStream( is);
			newer.setFileOutputStream( bos);
			return newer;
		}

		public InputStream getSavedStream() throws FileNotFoundException {
		    if( isFileBased)
				return new FileInputStream( file);
			else return new ByteArrayInputStream( bos.toByteArray());
		}

	// Attributes:
	    private final boolean isFileBased;
		private File file = null;
		private ByteArrayOutputStream bos = null;

	} // XInputSave

// Attributes:
    private static XRendererSupport _this = new XRendererSupport();
    private static XRendererContext context = null;

    public final static int MODE_IMAGES_TEMP = 0;
    public final static int MODE_IMAGES_ALONG = 1;

    final static String IMAGE_CACHE_PROPERTY = "imageCache";
    final static String SAVE_CACHE = "XBrowser Document Save Cache";
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -