View Javadoc

1   /*
2    * $Id: DatabaseConnectorFactory.java,v 1.17 2006/01/12 19:12:48 psionides Exp $
3    * 
4    */
5   package net.sourceforge.jdbdump.connect;
6   import java.io.File;
7   import java.io.IOException;
8   import java.net.JarURLConnection;
9   import java.net.URL;
10  import java.util.ArrayList;
11  import java.util.Enumeration;
12  import java.util.Iterator;
13  import java.util.jar.JarFile;
14  import java.util.zip.ZipEntry;
15  import org.apache.log4j.Logger;
16  
17  /***
18   * A DatabaseConnectorFactory is an object that lists all the database types that can be 
19   * backed up and creates connectors to the specific database types.
20   * Connectors are the objects that extend the DatabaseConnector class and provide methods that enable 
21   * you to create backup of a specific database.
22   * This class implements two design patterns: Factory and Singleton. 
23   * Factory pattern makes it easy to produce the proper databse connector. 
24   * Singleton pattern checks if there is only one instance of DatabaseConnectorFactory.
25   *  
26   * @author tomgur
27   *
28   */
29  
30  public class DatabaseConnectorFactory {
31  	/***an object providing Singleton desing pattern implementation */
32  	public static DatabaseConnectorFactory singleton = null; 
33  	
34  	/*** A log4j logger for this class. */
35  	private static Logger logger = Logger.getLogger(DatabaseConnectorFactory.class);
36  	
37  	
38  	/***
39  	 * 
40  	 * Imlements Singleton desing pattern 
41  	 * 
42  	 */
43  	public static DatabaseConnectorFactory getInstance(){
44  		if (singleton == null){
45  			synchronized(DatabaseConnectorFactory.class){
46  				DatabaseConnectorFactory localFactory = new DatabaseConnectorFactory();
47  				singleton = localFactory;
48  			}
49  		}
50  		
51  		return singleton;
52  	}
53  	/***
54  	 * Lists all database plugins that are available.
55  	 * @return a list of available classes extending DatabaseConnector
56  	 */
57  	public String[] listPlugins() {
58  		ArrayList<String> plugins = listPlugins("net.sourceforge.jdbdump.connect.connectors",
59  			"net.sourceforge.jdbdump.connect.DatabaseConnector");
60  		return (String[]) plugins.toArray(new String[0]);
61  	}
62  	
63  	/***
64  	 * Lists all the classes inheriting a given
65  	 * class in the currently loaded packages.
66  	 * @param tosubclassname the name of the class to inherit from
67  	 * @throws ClassNotFoundException
68  	 */
69  	public ArrayList<String> listPlugins(String tosubclassname) {
70  		ArrayList<String> pluginsTmp = new ArrayList<String>();
71  		ArrayList<String> plugins = new ArrayList<String>();
72  		String plugin;
73  		try {
74  			Class tosubclass = Class.forName(tosubclassname);
75  			Package [] pcks = Package.getPackages();
76  			for (int i=0;i<pcks.length;i++) {
77  				
78  				pluginsTmp = listPlugins(pcks[i].getName(), tosubclass);
79  				if(pluginsTmp != null) {
80  					for(Iterator it = pluginsTmp.iterator();it.hasNext();) {
81  						plugin = it.next().toString();
82  						plugins.add(plugin);
83  					}
84  				}
85  			}
86  		} 
87  		catch (ClassNotFoundException ex) {
88  			logger.warn("listPlugins(String tosubclassname): Error while finding class: " + ex);
89  		}
90  		
91  		return plugins;
92  	}
93  	
94  	
95  	/***
96  	 * Listss all the classes inheriting a given
97  	 * class in a given package.
98  	 * @param pckgname the fully qualified name of the package
99  	 * @param tosubclass the name of the class to inherit from
100 	 * @throws ClassNotFoundException
101 	 */
102 	public ArrayList<String> listPlugins(String pckname, String tosubclassname) {
103 		ArrayList<String> plugins = new ArrayList<String>();
104 		try {
105 			Class tosubclass = Class.forName(tosubclassname);
106 			plugins = listPlugins(pckname,tosubclass);
107 		} 
108 		catch (ClassNotFoundException e) {
109 			logger.error("listPlugins(String pckname, String tosubclassname): Error while finding class: " + e);
110 		}
111 		
112 		return plugins;
113 		
114 	}
115 	
116 	
117 	/***
118 	 * Lists all the classes inheriting a given
119 	 * class in a given package.
120 	 * @param pckgname the fully qualified name of the package
121 	 * @param tosubclass the Class object to inherit from
122 	 * @throws ClassNotFoundException
123 	 * @throws InstantiationException
124 	 * @throws IllegalAccessException
125 	 * @throws IOException
126 	 */
127 	public ArrayList<String> listPlugins(String pckgname, Class tosubclass) {
128 
129 		ArrayList<String> plugins = new ArrayList<String>();
130 		String plugin;
131 		// Translate the package name into an absolute path
132 		String name = new String(pckgname);
133 		if (!name.startsWith("/")) {
134 			name = "/" + name;
135 		}	
136 		name = name.replace('.','/');
137 
138 		// Get a File object for the package
139 		URL url = DatabaseConnectorFactory.class.getResource(name);
140 		// URL url = tosubclass.getResource(name);
141 		// URL url = ClassLoader.getSystemClassLoader().getResource(name);
142   	
143 		if (url==null) return null;
144 
145 		File directory = new File(url.getFile());
146 
147 		// directory has been found
148 		if (directory.exists()) {
149 			// Get the list of the files contained in the package
150 			String [] files = directory.list();
151 			for (int i=0;i<files.length;i++) {
152 		
153 				// we are only interested in .class files
154 				if (files[i].endsWith(".class")) {
155 					// removes the .class extension
156 					String classname = files[i].substring(0,files[i].length()-6);
157 					try {
158 						// Try to create an instance of the object
159 						Object o = Class.forName(pckgname+"."+classname).newInstance();
160 						if (tosubclass.isInstance(o)) {
161 							plugin = pckgname+"."+classname;
162 							//adding the name of the subclass to the arraylist
163 							plugins.add(plugin);
164 						}
165 					} 
166 					catch (ClassNotFoundException e) {
167 						logger.error("listPlugins(String pckgname, Class tosubclass): Error while finding class: " + e);
168 					} 
169 					catch (InstantiationException e) {
170 						// We try to instanciate an interface
171 						// or an object that does not have a 
172 						// default constructor
173 						logger.error("listPlugins(String pckgname, Class tosubclass): Error while instantiation: " + e);
174 					} 
175 					catch (IllegalAccessException e) {
176 						// The class is not public
177 						logger.error("listPlugins(String pckgname, Class tosubclass): Illegal Access Error: " + e);
178 					}
179 				}
180 			}
181 	
182 		} 
183 		else {
184 			try {
185 				// It does not work with the filesystem: we must
186 				// be in the case of a package contained in a jar file.
187 				JarURLConnection conn = (JarURLConnection)url.openConnection();
188 				String starts = conn.getEntryName();
189 				JarFile jfile = conn.getJarFile();
190 				Enumeration e = jfile.entries();
191 				while (e.hasMoreElements()) {
192 					ZipEntry entry = (ZipEntry)e.nextElement();
193 					String entryname = entry.getName();
194 					if (entryname.startsWith(starts)
195 						&&(entryname.lastIndexOf('/')<=starts.length())
196 						&&entryname.endsWith(".class")) 
197 					{
198 						String classname = entryname.substring(0,entryname.length()-6);
199 						if (classname.startsWith("/")) 
200 							classname = classname.substring(1);
201 						classname = classname.replace('/','.');
202 			    
203 						try {
204 							// Try to create an instance of the object
205 							Object o = Class.forName(classname).newInstance();
206 							if (tosubclass.isInstance(o)) {
207 								//System.out.println(classname.substring(classname.lastIndexOf('.')+1));
208 								plugin = classname.substring(classname.lastIndexOf('.')+1);
209 								plugins.add(plugin);
210 							}
211 						} 
212 						catch (ClassNotFoundException ex) {
213 							logger.error("listPlugins(String pckgname, Class tosubclass): Error while finding class: " + ex);
214 						} 
215 						catch (InstantiationException ex) {
216 							// We try to instanciate an interface
217 							// or an object that does not have a 
218 							// default constructor
219 							logger.error("listPlugins(String pckgname, Class tosubclass): Error while instantiation: " + ex);
220 						} 
221 						catch (IllegalAccessException iaex) {
222 							// The class is not public
223 							logger.error("listPlugins(String pckgname, Class tosubclass): Illegal Access Error: " + e);
224 						}
225 					}
226 				}
227 			} 
228 			catch (IOException e) {
229 				logger.error("listPlugins(String pckgname, Class tosubclass): IOExeption: " + e);
230 			}	
231 		}
232    
233 		return plugins;
234 	}
235 	/***
236 	 * Creates connector to the database on the basis of provided data and implements the Factory 
237 	 * design pattern
238 	 * @param name - name of the database plugin
239 	 * @throws ClassNotFoundException
240 	 * @throws InstantiationException
241 	 * @throws IllegalAccessException
242 	 */
243 	public DatabaseConnector createConnector(String name){
244 		 
245 		DatabaseConnector dbConnector = null;
246 		Class connectorClass;
247 		try{
248 			connectorClass = Class.forName(name);
249 			dbConnector = (DatabaseConnector)connectorClass.newInstance();
250 		}catch(ClassNotFoundException e){
251 			logger.error("createConnector(String name): Error while creating connector: " + e);
252 		}catch(InstantiationException e){
253 			logger.error("createConnector(String name): Error while creating connector: " + e);
254 		}catch(IllegalAccessException e){
255 			logger.error("createConnector(String name): Error while creating connector: " + e);
256 		}
257 		return dbConnector;
258 	}
259 
260 }