View Javadoc

1   /*
2    *  XNap - A P2P framework and client.
3    *
4    *  See the file AUTHORS for copyright information.
5    *
6    *  This program is free software; you can redistribute it and/or modify
7    *  it under the terms of the GNU General Public License as published by
8    *  the Free Software Foundation.
9    *
10   *  This program is distributed in the hope that it will be useful,
11   *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12   *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13   *  GNU General Public License for more details.
14   *
15   *  You should have received a copy of the GNU General Public License
16   *  along with this program; if not, write to the Free Software
17   *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18   */
19  
20  package org.xnap.pkg;
21  
22  import java.io.File;
23  import java.io.IOException;
24  import java.util.Properties;
25  
26  import org.apache.log4j.Logger;
27  import org.xnap.XNap;
28  import org.xnap.gui.component.ProgressMonitor;
29  import org.xnap.loader.XNapClassLoader;
30  import org.xnap.util.FileHelper;
31  import org.xnap.util.Preferences;
32  
33  /***
34   * 
35   */
36  public class XNapPackageManager extends PackageManager {
37  
38      //--- Constant(s) ---
39  
40  	public static final String AVAILABLE_FILENAME 
41  		= FileHelper.getHomeDir() + "available";
42  
43  	public static final String SOURCES_FILENAME 
44  		= FileHelper.getHomeDir() + "sources.list";
45  
46  	public static final String STATUS_FILENAME 
47  		= FileHelper.getHomeDir() + "status";
48  
49      //--- Data field(s) ---
50  
51      private static Logger logger = Logger.getLogger(XNapPackageManager.class);
52  	private static XNapPackageManager singleton = new XNapPackageManager();
53  	private boolean initialized;
54  
55      //--- Constructor(s) ---
56  
57      private XNapPackageManager()
58      {
59      }
60  
61      //--- Method(s) ---
62  
63  	public static XNapPackageManager getInstance()
64  	{
65  		return singleton;
66  	}
67  
68  	public PackageInfo createFakePackage(File file)
69  	{
70  		if (!file.getName().endsWith(".jar")) {
71  			throw new IllegalArgumentException("Not a jar file.");
72  		}
73  		String filename 
74  			= file.getName().substring(0, file.getName().length() - 4);
75  
76  		PackageInfo info = new PackageInfo();
77  
78  		int i = filename.lastIndexOf("-");
79  		if (i < 0 || i == filename.length() - 1) {
80  			info.setPackage(filename);
81  			info.setVersion("1.0");
82  		}
83  		else {
84  			info.setPackage(filename.substring(0, i));
85  			info.setVersion(filename.substring(i + 1, filename.length()));
86  		}
87  		info.setClassPath(new String[] { file.getName() });
88  		info.setControlPath(file.getParentFile().getAbsolutePath());
89  		info.setSection("local");
90  		info.setDescription(XNap.tr("Locally installed jar file."));
91  		info.setStatus(PackageInfo.STATUS_INSTALLED);
92  
93  		return info;
94  	}
95  
96  	/***
97  	 * Adds installed packages and saves the list of packages to
98  	 * {@link #AVAILABLE_FILENAME}.  
99  	 */
100 	public void discover() 
101 	{
102 		File pathes[] = XNapClassLoader.getSearchPath();
103 		for (int i = 0; i < pathes.length; i++) {
104 			discover(pathes[i]);
105 		}
106 
107 		String pathnames[] = Preferences.getInstance().getJarIncludePath();
108 		for (int i = 0; i < pathnames.length; i++) {
109 			discover(new File(pathnames[i]));
110 		}
111 	}
112 
113 	/***
114 	 * Adds all packages found in path and recursively in all sub directories.
115 	 */
116 	public void discover(File path)
117 	{
118 		File[] files = path.listFiles();
119 		if (files != null) {
120 			boolean isXNapPackage = false;
121 			for (int i = 0; i < files.length; i++) {
122 				if (files[i].isDirectory()) {
123 					discover(files[i]);
124 				}
125 				else if (files[i].getName().equals("control")) {
126 					try {
127 						Properties table = new Properties();
128 						table.put("Control-Path", path.getAbsolutePath());
129 						table.put("Status", PackageInfo.STATUS_INSTALLED);
130 						read(files[i], table);
131 						isXNapPackage = true;
132 					}
133 					catch (IOException e) {
134 						// we should handle this
135 					}
136 				}
137 			}
138 				
139 			if (isXNapPackage) {
140 				// do not add fake jar packages to avoid duplication
141 				return;
142 			}
143 
144 			for (int i = 0; i < files.length; i++) {
145 				if (files[i].getName().endsWith(".jar")) {
146 					PackageInfo info = createFakePackage(files[i]);
147 					add(info);
148 				}
149 			}
150 		}
151 	}
152 
153 	public String getDefaultSources(boolean includeUnstable)
154 	{
155 		StringBuffer sb = new StringBuffer();
156 		sb.append("http://xnap.sf.net/stable/packages.gz"
157 				  + " http://xnap.sf.net/stable/mirrors.list\n");
158 		if (!includeUnstable) {
159 			sb.append("#");
160 		}
161 		sb.append("http://xnap.sf.net/unstable/packages.gz"
162 				  + " http://xnap.sf.net/stable/mirrors.list\n");
163 		return sb.toString();
164 	}
165 
166 	public String getDefaultSources()
167 	{
168 		return getDefaultSources(false);
169 	}
170 	
171 	public void initialize()
172 	{
173 		if (!initialized) {
174 			initialized = true;
175 
176 			logger.info("Initializing package manager");
177 			if (XNap.isRunFromCvs()) {
178 				try {
179 					Properties table = new Properties();
180 					table.put("Class-Path", "");
181 					table.put("Depends", "");
182 					table.put("Status", PackageInfo.STATUS_INSTALLED);
183 					read(new File("metainfo/control"), table);
184 				}
185 				catch (IOException e) {
186 					logger.debug("error reading control file", e);
187 				}
188 				return;
189 			}
190 
191 			if (XNap.clearPackageInfos) {
192 				// do not read package files, search hard disk instead
193 				discover();
194 			}
195 			else {
196 				File f = new File(STATUS_FILENAME);
197 				if (f.exists()) {
198 					try {
199 						read(new File(STATUS_FILENAME));
200 					}
201 					catch (IOException e) {
202 						logger.debug("error reading status file", e);
203 					}
204 				}
205 				else {
206 					discover();
207 				}
208 				
209 				try {
210 					read(new File(AVAILABLE_FILENAME));
211 				}
212 				catch (IOException e) {
213 					logger.debug("error reading available file", e);
214 				}
215 			}
216 
217 			write();
218 		}
219 	}
220 
221 	/***
222 	 * Updates the list of packages from the urls specified in {@link
223 	 * #SOURCES_FILENAME}.
224 	 *
225 	 * <p>This method runs asynchronus. Make sure the package manager
226 	 * is not modified until monitor.done() is invoked.
227 	 */
228 	public void update(ProgressMonitor monitor)
229 	{
230   		PackageUpdater updater = new PackageUpdater
231   			(this, new File(SOURCES_FILENAME), monitor);
232   		Thread t = new Thread(updater, "PackageUpdater");
233 		if (monitor != null) {
234 			monitor.setThread(t);
235 		}
236   		t.start();
237 	}
238 
239 	/***
240 	 * Saves the list of packages.
241 	 */
242 	public void write()
243 	{
244 		try {
245 			write(new File(STATUS_FILENAME), new File(AVAILABLE_FILENAME));
246 		}
247 		catch (IOException e) {
248 			logger.warn("Error writing list of packages", e);
249 		}
250 	}
251 
252 	private void write(File statusFile, File availableFile) throws IOException
253 	{
254 		// save list of installed packages
255 		Properties table = new Properties();
256 		table.put("Status", PackageInfo.STATUS_INSTALLED);
257 		write(statusFile, table);
258 
259 		// save other packages
260 		table = new Properties();
261 		table.put("Available", "True");
262 		write(availableFile, table);
263 	}
264 
265 }
266