PageRenderTime 64ms CodeModel.GetById 39ms app.highlight 22ms RepoModel.GetById 1ms app.codeStats 0ms

/jEdit/tags/jedit-4-2-pre4/org/gjt/sp/jedit/pluginmgr/Roster.java

#
Java | 487 lines | 351 code | 70 blank | 66 comment | 53 complexity | 0884161cba8172c2af895ab47fa0569f MD5 | raw file
  1/*
  2 * Roster.java - A list of things to do, used in various places
  3 * :tabSize=8:indentSize=8:noTabs=false:
  4 * :folding=explicit:collapseFolds=1:
  5 *
  6 * Copyright (C) 2001, 2003 Slava Pestov
  7 *
  8 * This program is free software; you can redistribute it and/or
  9 * modify it under the terms of the GNU General Public License
 10 * as published by the Free Software Foundation; either version 2
 11 * of the License, or any later version.
 12 *
 13 * This program is distributed in the hope that it will be useful,
 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 16 * GNU General Public License for more details.
 17 *
 18 * You should have received a copy of the GNU General Public License
 19 * along with this program; if not, write to the Free Software
 20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 21 */
 22
 23package org.gjt.sp.jedit.pluginmgr;
 24
 25//{{{ Imports
 26import javax.swing.SwingUtilities;
 27import java.awt.Component;
 28import java.io.*;
 29import java.net.*;
 30import java.util.zip.*;
 31import java.util.*;
 32import org.gjt.sp.jedit.*;
 33import org.gjt.sp.util.Log;
 34//}}}
 35
 36class Roster
 37{
 38	//{{{ Roster constructor
 39	Roster()
 40	{
 41		operations = new ArrayList();
 42		toLoad = new ArrayList();
 43	} //}}}
 44
 45	//{{{ addRemove() method
 46	void addRemove(String plugin)
 47	{
 48		addOperation(new Remove(plugin));
 49	} //}}}
 50
 51	//{{{ addInstall() method
 52	void addInstall(String installed, String url, String installDirectory,
 53		int size)
 54	{
 55		addOperation(new Install(installed,url,installDirectory,size));
 56	} //}}}
 57
 58	//{{{ getOperation() method
 59	public Operation getOperation(int i)
 60	{
 61		return (Operation)operations.get(i);
 62	} //}}}
 63
 64	//{{{ getOperationCount() method
 65	int getOperationCount()
 66	{
 67		return operations.size();
 68	} //}}}
 69
 70	//{{{ isEmpty() method
 71	boolean isEmpty()
 72	{
 73		return operations.size() == 0;
 74	} //}}}
 75
 76	//{{{ performOperationsInWorkThread() method
 77	void performOperationsInWorkThread(PluginManagerProgress progress)
 78	{
 79		for(int i = 0; i < operations.size(); i++)
 80		{
 81			Operation op = (Operation)operations.get(i);
 82			op.runInWorkThread(progress);
 83			progress.done();
 84
 85			if(Thread.interrupted())
 86				return;
 87		}
 88	} //}}}
 89
 90	//{{{ performOperationsInAWTThread() method
 91	void performOperationsInAWTThread(Component comp)
 92	{
 93		for(int i = 0; i < operations.size(); i++)
 94		{
 95			Operation op = (Operation)operations.get(i);
 96			op.runInAWTThread(comp);
 97		}
 98
 99		// add the JARs before checking deps since dep check might
100		// require all JARs to be present
101		for(int i = 0; i < toLoad.size(); i++)
102		{
103			String pluginName = (String)toLoad.get(i);
104			if(jEdit.getPluginJAR(pluginName) != null)
105			{
106				Log.log(Log.WARNING,this,"Already loaded: "
107					+ pluginName);
108			}
109			else
110				jEdit.addPluginJAR(pluginName);
111		}
112
113		for(int i = 0; i < toLoad.size(); i++)
114		{
115			String pluginName = (String)toLoad.get(i);
116			PluginJAR plugin = jEdit.getPluginJAR(pluginName);
117			if(plugin != null)
118				plugin.checkDependencies();
119		}
120
121		// now activate the plugins
122		for(int i = 0; i < toLoad.size(); i++)
123		{
124			String pluginName = (String)toLoad.get(i);
125			PluginJAR plugin = jEdit.getPluginJAR(pluginName);
126			if(plugin != null)
127				plugin.activatePluginIfNecessary();
128		}
129	} //}}}
130
131	//{{{ Private members
132	private static File downloadDir;
133
134	private List operations;
135	private List toLoad;
136
137	//{{{ addOperation() method
138	private void addOperation(Operation op)
139	{
140		for(int i = 0; i < operations.size(); i++)
141		{
142			if(operations.get(i).equals(op))
143				return;
144		}
145
146		operations.add(op);
147	} //}}}
148
149	//{{{ getDownloadDir() method
150	private static String getDownloadDir()
151	{
152		if(downloadDir == null)
153		{
154			String settings = jEdit.getSettingsDirectory();
155			if(settings == null)
156				settings = System.getProperty("user.home");
157			downloadDir = new File(MiscUtilities.constructPath(
158				settings,"PluginManager.download"));
159			downloadDir.mkdirs();
160		}
161
162		return downloadDir.getPath();
163	} //}}}
164
165	//}}}
166
167	//{{{ Operation interface
168	static abstract class Operation
169	{
170		public void runInWorkThread(PluginManagerProgress progress)
171		{
172		}
173
174		public void runInAWTThread(Component comp)
175		{
176		}
177
178		public int getMaximum()
179		{
180			return 0;
181		}
182	} //}}}
183
184	//{{{ Remove class
185	class Remove extends Operation
186	{
187		//{{{ Remove constructor
188		Remove(String plugin)
189		{
190			this.plugin = plugin;
191		} //}}}
192
193		//{{{ runInAWTThread() method
194		public void runInAWTThread(Component comp)
195		{
196			// close JAR file and all JARs that depend on this
197			PluginJAR jar = jEdit.getPluginJAR(plugin);
198			if(jar != null)
199			{
200				unloadPluginJAR(jar);
201				String cachePath = jar.getCachePath();
202				if(cachePath != null)
203					new File(cachePath).delete();
204			}
205
206			toLoad.remove(plugin);
207
208			// remove cache file
209
210			// move JAR first
211			File jarFile = new File(plugin);
212			File srcFile = new File(plugin.substring(0,plugin.length() - 4));
213
214			Log.log(Log.NOTICE,this,"Deleting " + jarFile);
215
216			boolean ok = jarFile.delete();
217
218			if(srcFile.exists())
219				ok &= deleteRecursively(srcFile);
220
221			if(!ok)
222			{
223				String[] args = { plugin };
224				GUIUtilities.error(comp,"plugin-manager.remove-failed",args);
225			}
226		} //}}}
227
228		//{{{ unloadPluginJAR() method
229		/**
230		 * This should go into a public method somewhere.
231		 */
232		private void unloadPluginJAR(PluginJAR jar)
233		{
234			String[] dependents = jar.getDependentPlugins();
235			for(int i = 0; i < dependents.length; i++)
236			{
237				PluginJAR _jar = jEdit.getPluginJAR(
238					dependents[i]);
239				if(_jar != null)
240				{
241					toLoad.add(dependents[i]);
242					unloadPluginJAR(_jar);
243				}
244			}
245
246			jEdit.removePluginJAR(jar,false);
247		} //}}}
248
249		//{{{ equals() method
250		public boolean equals(Object o)
251		{
252			if(o instanceof Remove
253				&& ((Remove)o).plugin.equals(plugin))
254				return true;
255			else
256				return false;
257		} //}}}
258
259		//{{{ Private members
260		private String plugin;
261
262		private boolean deleteRecursively(File file)
263		{
264			Log.log(Log.NOTICE,this,"Deleting " + file + " recursively");
265
266			boolean ok = true;
267
268			if(file.isDirectory())
269			{
270				String path = file.getPath();
271				String[] children = file.list();
272				for(int i = 0; i < children.length; i++)
273				{
274					ok &= deleteRecursively(new File(path,children[i]));
275				}
276			}
277
278			ok &= file.delete();
279
280			return ok;
281		} //}}}
282	} //}}}
283
284	//{{{ Install class
285	class Install extends Operation
286	{
287		int size;
288
289		//{{{ Install constructor
290		Install(String installed, String url, String installDirectory,
291			int size)
292		{
293			// catch those hooligans passing null urls
294			if(url == null)
295				throw new NullPointerException();
296
297			this.installed = installed;
298			this.url = url;
299			this.installDirectory = installDirectory;
300			this.size = size;
301		} //}}}
302
303		//{{{ getMaximum() method
304		public int getMaximum()
305		{
306			return size;
307		} //}}}
308
309		//{{{ runInWorkThread() method
310		public void runInWorkThread(PluginManagerProgress progress)
311		{
312			String fileName = MiscUtilities.getFileName(url);
313
314			path = download(progress,fileName,url);
315		} //}}}
316
317		//{{{ runInAWTThread() method
318		public void runInAWTThread(Component comp)
319		{
320			// check if download failed
321			if(path == null)
322				return;
323
324			// if download OK, remove existing version
325			if(installed != null)
326				new Remove(installed).runInAWTThread(comp);
327
328			ZipFile zipFile = null;
329
330			try
331			{
332				zipFile = new ZipFile(path);
333
334				Enumeration enum = zipFile.entries();
335				while(enum.hasMoreElements())
336				{
337					ZipEntry entry = (ZipEntry)enum.nextElement();
338					String name = entry.getName().replace('/',File.separatorChar);
339					File file = new File(installDirectory,name);
340					if(entry.isDirectory())
341						file.mkdirs();
342					else
343					{
344						new File(file.getParent()).mkdirs();
345						copy(null,
346							zipFile.getInputStream(entry),
347							new FileOutputStream(
348							file),false);
349						if(file.getName().toLowerCase().endsWith(".jar"))
350							toLoad.add(file.getPath());
351					}
352				}
353			}
354			catch(InterruptedIOException iio)
355			{
356			}
357			catch(final IOException io)
358			{
359				Log.log(Log.ERROR,this,io);
360
361				String[] args = { io.getMessage() };
362				GUIUtilities.error(null,"ioerror",args);
363			}
364			catch(Exception e)
365			{
366				Log.log(Log.ERROR,this,e);
367			}
368			finally
369			{
370				try
371				{
372					if(zipFile != null)
373						zipFile.close();
374				}
375				catch(IOException io)
376				{
377					Log.log(Log.ERROR,this,io);
378				}
379
380				if(jEdit.getBooleanProperty(
381					"plugin-manager.deleteDownloads"))
382				{
383					new File(path).delete();
384				}
385			}
386		} //}}}
387
388		//{{{ equals() method
389		public boolean equals(Object o)
390		{
391			if(o instanceof Install
392				&& ((Install)o).url.equals(url))
393			{
394				/* even if installDirectory is different */
395				return true;
396			}
397			else
398				return false;
399		} //}}}
400
401		//{{{ Private members
402		private String installed;
403		private String url;
404		private String installDirectory;
405		private String path;
406
407		//{{{ download() method
408		private String download(PluginManagerProgress progress,
409			String fileName, String url)
410		{
411			try
412			{
413				URLConnection conn = new URL(url).openConnection();
414
415				String path = MiscUtilities.constructPath(getDownloadDir(),fileName);
416
417				if(!copy(progress,conn.getInputStream(),
418					new FileOutputStream(path),true))
419					return null;
420
421				return path;
422			}
423			catch(InterruptedIOException iio)
424			{
425				// do nothing, user clicked 'Stop'
426				return null;
427			}
428			catch(final IOException io)
429			{
430				Log.log(Log.ERROR,this,io);
431
432				SwingUtilities.invokeLater(new Runnable()
433				{
434					public void run()
435					{
436						String[] args = { io.getMessage() };
437						GUIUtilities.error(null,"ioerror",args);
438					}
439				});
440
441				return null;
442			}
443			catch(Exception e)
444			{
445				Log.log(Log.ERROR,this,e);
446
447				return null;
448			}
449		} //}}}
450
451		//{{{ copy() method
452		private boolean copy(PluginManagerProgress progress,
453			InputStream in, OutputStream out, boolean canStop)
454			throws Exception
455		{
456			in = new BufferedInputStream(in);
457			out = new BufferedOutputStream(out);
458
459			byte[] buf = new byte[4096];
460			int copied = 0;
461loop:			for(;;)
462			{
463				int count = in.read(buf,0,buf.length);
464				if(count == -1)
465					break loop;
466
467				copied += count;
468				if(progress != null)
469					progress.setValue(copied);
470
471				out.write(buf,0,count);
472				if(canStop && Thread.interrupted())
473				{
474					in.close();
475					out.close();
476					return false;
477				}
478			}
479
480			in.close();
481			out.close();
482			return true;
483		} //}}}
484
485		//}}}
486	} //}}}
487}