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.search;
21  
22  import java.io.File;
23  import java.io.FileInputStream;
24  import java.io.IOException;
25  import java.io.InputStream;
26  import java.util.Iterator;
27  import java.util.LinkedList;
28  import java.util.List;
29  import java.util.Properties;
30  import java.util.StringTokenizer;
31  
32  import org.apache.log4j.Logger;
33  import org.xnap.XNap;
34  import org.xnap.event.ListEvent;
35  import org.xnap.event.ListListener;
36  import org.xnap.event.ListSupport;
37  import org.xnap.util.FileHelper;
38  
39  /***
40   * Manages search providers. SearchManager follows the singleton pattern.
41   */
42  public class SearchManager
43  {
44  
45      //--- Constant(s) ---
46  
47      public static String MEDIA_TYPE_FILE = "mediatypes.properties";
48  
49      /***
50       * Default media type that matches anything.
51       */
52      public static MediaType MEDIA_ANYTHING = new AnythingMediaType();
53  
54      /***
55       * Default media type that matches audio files.
56       */
57      public static MediaType MEDIA_AUDIO 
58  		= new DefaultMediaType("audio", XNap.tr("Audio"));
59  
60      /***
61       * Default media type that matches document files.
62       */
63      public static MediaType MEDIA_DOCUMENTS 
64  		= new DefaultMediaType("text", XNap.tr("Documents"));
65  
66      /***
67       * Default media type that matches image files.
68       */
69      public static MediaType MEDIA_IMAGES 
70  		= new DefaultMediaType("image", XNap.tr("Images"));
71  
72      /***
73       * Default media type that matches software files.
74       */
75      public static MediaType MEDIA_SOFTWARE 
76  		= new DefaultMediaType("application", XNap.tr("Software"));
77  
78      /***
79       * Default media type that matches video files.
80       */
81      public static MediaType MEDIA_VIDEO 
82  		= new DefaultMediaType("video", XNap.tr("Video"));
83  
84      public static MediaType[] DEFAULT_MEDIA_TYPES = {
85  		MEDIA_ANYTHING, MEDIA_AUDIO, MEDIA_DOCUMENTS, MEDIA_IMAGES, 
86  		MEDIA_SOFTWARE,	MEDIA_VIDEO,
87      };
88  
89      //--- Data field(s) ---
90  
91      private static Logger logger = Logger.getLogger(SearchManager.class);
92      private static SearchManager instance = new SearchManager();
93  
94      private SearchManagerListener listener = null;
95  
96      private List providers = new LinkedList();
97      private ListSupport providerSupport = new ListSupport(this);
98  
99      //--- Constructor(s) ---
100 
101     private SearchManager()
102     {
103 		initializeMediaTypes();
104     }
105 
106     //--- Method(s) ---
107 
108     /***
109      * Returns the instance of <code>SearchManager</code>.
110      */
111     public static SearchManager getInstance()
112     {
113 		return instance;
114     }
115 
116 	public static MediaType getMediaType(String filename)
117 	{
118 		// skip anything media type
119 		for (int i = 1; i < DEFAULT_MEDIA_TYPES.length; i++) {
120 			if (DEFAULT_MEDIA_TYPES[i].matches(filename)) {
121 				return DEFAULT_MEDIA_TYPES[i];
122 			}
123 		}
124 		return null;
125 	}
126 
127     /***
128      * Adds <code>provider</code> to the list of available search providers. 
129      */
130     public synchronized void add(SearchProvider provider)
131     {
132 		providers.add(provider);
133 		providerSupport.fireItemAdded(provider);
134     }
135 
136     /***
137      * <code>Listener</code> is notified when a new search provider is 
138      * added.
139      */
140     public synchronized void addListListener(ListListener listener)
141     {
142 		providerSupport.addListListener(listener);
143 		for (Iterator i = providers.iterator(); i.hasNext();) {
144 			listener.itemAdded
145 				(new ListEvent(this, ListEvent.ITEM_ADDED, i.next()));
146 		}
147     }
148 
149     /***
150      * Asks the search manager to handle <code>search</code>. The search object
151      * is passed to the listener that starts the search and displays the
152      * results. If no listener is set nothing happens.
153      *
154      * @see SearchManagerListener
155      */
156     public synchronized void handle(Search search)
157     {
158 		if (listener != null) {
159 			listener.handle(search);
160 		}
161     }
162 
163     /***
164      * Reads the extensions for the default media types from a property file.
165      */
166     public void initializeMediaTypes()
167     {
168 		Properties props = new Properties();
169 		InputStream in = null;
170 		try {
171 			File f = new File(FileHelper.getHomeDir() + MEDIA_TYPE_FILE);
172 			if (f.exists()) {
173 				logger.debug("reading media types file: " + f);
174 				in = new FileInputStream(f);
175 				props.load(in);
176 			}
177 			else {
178 				in = FileHelper.getResourceAsStream(MEDIA_TYPE_FILE);
179 				if (in != null) {
180 					logger.debug("reading media types resource: " 
181 								 + MEDIA_TYPE_FILE);
182 					props.load(in);
183 				}
184 				else {
185 					logger.debug("media types file not found");
186 				}
187 
188 			}
189 		} 
190 		catch (IOException e) {
191 			logger.debug("could not read media types file", e);
192 		}
193 		finally {
194 			try {
195 				if (in != null) {
196 					in.close();
197 				}
198 			}
199 			catch (Exception e) {
200 			}
201 		}
202 
203 		if (props != null) {
204 			// skip MEDIA_ANYTHING
205 			for (int i = 1; i < DEFAULT_MEDIA_TYPES.length; i++) {
206 				String key = DEFAULT_MEDIA_TYPES[i].getRealm();
207 				String extensions = props.getProperty(key, "");
208 				StringTokenizer t = new StringTokenizer(extensions, ";");
209 				// add extensions
210 				while (t.hasMoreTokens()) {
211 					DefaultMediaType dmt
212 						= (DefaultMediaType)DEFAULT_MEDIA_TYPES[i];
213 					dmt.add(t.nextToken());
214 				}
215 			}
216 		}
217     }
218 
219 
220     /***
221      * Removes <code>provider</code> from the list of available search 
222      * providers. 
223      */
224     public synchronized void remove(SearchProvider provider)
225     {
226 		providers.remove(provider);
227 		providerSupport.fireItemRemoved(provider);
228     }
229 
230     /***
231      * <code>Listener</code> is notified when a new search provider is 
232      * removed.
233      */
234     public void removeListListener(ListListener listener)
235     {
236 		providerSupport.removeListListener(listener);
237     }
238 
239     /***
240      * Returns a new <code>SearchContainer</code> that searches all networks.
241      */
242     public synchronized Search searchAll(SearchFilter filter)
243     {
244 		SearchContainer c = new SearchContainer(filter);
245 
246 		for (Iterator i = providers.iterator(); i.hasNext();) {
247 			c.add(((SearchProvider)i.next()).search(filter));
248 		}
249 
250 		return c;
251     }
252 
253     /***
254      * Registers <code>listener</code> as the user search handler.
255      */
256     public synchronized void setListener(SearchManagerListener listener)
257     {
258 		this.listener = listener;
259     }
260     
261 }