001: /*
002: * @version 1.0.0.0
003: * @since Enhydra5.1
004: * @author Sasa Bojanic
005: * @author Nenad Stefanovic
006: * @author Zoran Milakovic
007: * @author Sinisa Milosevic
008: */
009:
010: package org.enhydra.util;
011:
012: import java.io.File;
013: import java.io.FileFilter;
014: import java.io.InputStream;
015: import java.lang.reflect.Method;
016: import java.util.ArrayList;
017: import java.util.Collection;
018: import java.util.Enumeration;
019: import java.util.HashSet;
020: import java.util.Iterator;
021: import java.util.List;
022: import java.util.Set;
023: import java.util.jar.JarFile;
024: import java.util.zip.ZipEntry;
025:
026: import javax.xml.parsers.DocumentBuilder;
027: import javax.xml.parsers.DocumentBuilderFactory;
028:
029: import org.w3c.dom.Document;
030: import org.w3c.dom.Element;
031: import org.w3c.dom.NodeList;
032:
033: import com.lutris.appserver.server.Enhydra;
034: import com.lutris.logging.Logger;
035: import com.lutris.util.Config;
036:
037: /**
038: * Utility methods.
039: */
040: public class Utils {
041:
042: /**
043: * Returns a List of DODS classes that represents the Database tables which are
044: * used by application given by it's name, and are cached.
045: */
046: public static List getCachedDOClassesForApplication(Config cfg,
047: ClassLoader cl) {
048: List retVal = new ArrayList();
049: boolean loaded = false;
050:
051: String[] databaseNames;
052: //get classes from doml file
053: try {
054: databaseNames = cfg.getStrings("DatabaseManager.Databases");
055: for (int i = 0; i < databaseNames.length; i++) {
056: String databaseName = databaseNames[i];
057: Object domlPath = cfg.get("DatabaseManager.DB."
058: + databaseName + ".domlFile");
059: if (domlPath != null)
060: retVal.addAll(getCachedDOClassesFromDoml(domlPath
061: .toString(), cl, databaseName));
062: }
063: if (retVal.isEmpty())
064: loaded = false;
065: else
066: loaded = true;
067: } catch (Throwable e) {
068: retVal.clear();
069: loaded = false;
070: }
071:
072: //get classes from doml on class path
073: if (!loaded) {
074: try {
075: databaseNames = cfg
076: .getStrings("DatabaseManager.Databases");
077:
078: for (int i = 0; i < databaseNames.length; i++) {
079: String databaseName = databaseNames[i];
080: Object domlPath = cfg.get("DatabaseManager.DB."
081: + databaseName + ".DomlClasspath");
082: String domlClassPathName = domlPath.toString();
083: InputStream domlStream = cl
084: .getResourceAsStream(domlClassPathName);
085: if (domlStream != null) {
086: retVal.addAll(getCachedDOClassesFromDoml(
087: domlStream, cl, databaseName));
088: } else {
089: Enhydra
090: .getLogChannel()
091: .write(
092: Logger.DEBUG,
093: "Resource "
094: + domlClassPathName
095: + " don't exist on application classpath!");
096: }
097: }
098:
099: if (retVal.isEmpty())
100: loaded = false;
101: else
102: loaded = true;
103:
104: } catch (Throwable e) {
105: retVal.clear();
106: loaded = false;
107: //e.printStackTrace();
108: }
109:
110: }
111:
112: //get classes from list in xml file
113: if (!loaded) {
114: try {
115: databaseNames = cfg
116: .getStrings("DatabaseManager.Databases");
117: for (int i = 0; i < databaseNames.length; i++) {
118: String databaseName = databaseNames[i];
119: // System.out.println("databaseName "+databaseName);
120: Object classList = cfg.get("DatabaseManager.DB."
121: + databaseName + ".ClassList");
122: if (classList != null) {
123: retVal.addAll(getCachedDOClassesFromClassList(
124: new File(classList.toString()), cl,
125: databaseName));
126: }
127: }
128: if (retVal.isEmpty())
129: loaded = false;
130: else
131: loaded = true;
132: } catch (Throwable e) {
133: retVal.clear();
134: loaded = false;
135: }
136: }
137:
138: //get classes from list in xml file, when xml file is in classpath
139: if (!loaded) {
140: try {
141: databaseNames = cfg
142: .getStrings("DatabaseManager.Databases");
143: InputStream classListStream = cl
144: .getResourceAsStream("org/enhydra/dods/DODSClassList.xml");
145: if (classListStream != null) {
146: retVal
147: .addAll(getCachedDOClassesFromClassListAsResource(
148: classListStream, cl,
149: databaseNames[0]));
150: } else {
151: Enhydra
152: .getLogChannel()
153: .write(Logger.DEBUG,
154: "Resource org/enhydra/dods/DODSClassList.xml don't exist !");
155: }
156: if (retVal.isEmpty())
157: loaded = false;
158: else
159: loaded = true;
160: } catch (Throwable e) {
161: retVal.clear();
162: loaded = false;
163: }
164: }
165:
166: //get classes from classpath
167: if (!loaded) {
168: //Get the classpath from the config file.
169: String[] classPath = new String[0];
170: String cpKey = "Server.ClassPath";
171: if (cfg.containsKey(cpKey)) {
172: try {
173: classPath = cfg.getStrings(cpKey);
174: return getCachedDOClassesForPath(classPath[0], cl,
175: "");
176: } catch (Throwable ex) {
177: // ex.printStackTrace();
178: }
179: }
180: }
181: return retVal;
182: }
183:
184: /**
185: * Find class names in specified doml file and add this classes in cache.
186: * @param domlPath path to doml file
187: * @param cl class loader
188: * @return list with loaded classes
189: */
190: public static List getCachedDOClassesFromDoml(InputStream doml,
191: ClassLoader cl, String databaseName) {
192: List retVal = new ArrayList();
193: try {
194:
195: // File domlFile = new File(domlPath);
196: DocumentBuilderFactory factory = DocumentBuilderFactory
197: .newInstance();
198: DocumentBuilder builder = factory.newDocumentBuilder();
199: // if( domlFile.exists() ) {
200: Document doc = builder.parse(doml);
201: NodeList tableNodes = doc.getElementsByTagName("table");
202: for (int i = 0; i < tableNodes.getLength(); i++) {
203: String tableName = ((Element) tableNodes.item(i))
204: .getAttribute("id");
205: if (tableName.startsWith("root."))
206: tableName = tableName.substring(5, tableName
207: .length());
208: String tableClassName = tableName + "DO";
209: //System.out.println("Trying to load class "+tableClassName);
210: Class cls = cl.loadClass(tableClassName);
211: // if this is a cached DO class,
212: // must contain methods getCacheDodsTableName() and refreshCache()
213: // I am searching for these methods, and if there are no
214: // such methods, exception will be thrown, and className
215: // won't be added to the list
216: Method mth;
217: mth = cls.getMethod("refreshCache", new Class[] {});
218: mth = cls.getMethod("getConfigurationAdministration",
219: new Class[] {});
220: retVal.add(new DOTable(databaseName, cls));
221: //retVal.add(cls);
222: }
223: // } else {
224: // Enhydra.getLogChannel().write(Logger.DEBUG,
225: // "Doml file "+domlPath+" don't exist !");
226: // }
227:
228: } catch (Throwable e) {
229: e.printStackTrace();
230: }
231: return retVal;
232: }
233:
234: /**
235: * Find class names in specified doml file and add this classes in cache.
236: * @param domlPath path to doml file
237: * @param cl class loader
238: * @return list with loaded classes
239: */
240: public static List getCachedDOClassesFromDoml(String domlPath,
241: ClassLoader cl, String databaseName) {
242: List retVal = new ArrayList();
243: try {
244:
245: File domlFile = new File(domlPath);
246: DocumentBuilderFactory factory = DocumentBuilderFactory
247: .newInstance();
248: DocumentBuilder builder = factory.newDocumentBuilder();
249: if (domlFile.exists()) {
250: Document doc = builder.parse(domlFile);
251: NodeList tableNodes = doc.getElementsByTagName("table");
252: for (int i = 0; i < tableNodes.getLength(); i++) {
253: String tableName = ((Element) tableNodes.item(i))
254: .getAttribute("id");
255: if (tableName.startsWith("root."))
256: tableName = tableName.substring(5, tableName
257: .length());
258: String tableClassName = tableName + "DO";
259: //System.out.println("Trying to load class "+tableClassName);
260: Class cls = cl.loadClass(tableClassName);
261: // if this is a cached DO class,
262: // must contain methods getCacheDodsTableName() and refreshCache()
263: // I am searching for these methods, and if there are no
264: // such methods, exception will be thrown, and className
265: // won't be added to the list
266: Method mth;
267: mth = cls.getMethod("refreshCache", new Class[] {});
268: mth = cls.getMethod(
269: "getConfigurationAdministration",
270: new Class[] {});
271: retVal.add(new DOTable(databaseName, cls));
272: }
273: } else {
274: Enhydra.getLogChannel().write(Logger.DEBUG,
275: "Doml file " + domlPath + " don't exist !");
276: }
277:
278: } catch (Throwable e) {
279: // e.printStackTrace();
280: Enhydra
281: .getLogChannel()
282: .write(Logger.DEBUG,
283: "Loading DO classes from doml file was unsuccessful!");
284: }
285: return retVal;
286: }
287:
288: /**
289: * Find class names in specified ClassList file and add this classes in cache.
290: * @param classListPath path to ClassList file
291: * @param cl class loader
292: * @return list with loaded classes
293: */
294: public static List getCachedDOClassesFromClassList(
295: File classListFile, ClassLoader cl, String databaseName) {
296: List retVal = new ArrayList();
297: try {
298:
299: DocumentBuilderFactory factory = DocumentBuilderFactory
300: .newInstance();
301: DocumentBuilder builder = factory.newDocumentBuilder();
302: if (classListFile.exists()) {
303: Document doc = builder.parse(classListFile);
304: NodeList classesNodes = doc
305: .getElementsByTagName("CLASSES");
306: for (int j = 0; j < classesNodes.getLength(); j++) {
307: Element docClasses = (Element) classesNodes.item(j);
308: String dbName = ((Element) classesNodes.item(j))
309: .getAttribute("databaseName");
310: if (dbName == null || dbName.equals(""))
311: dbName = databaseName;
312:
313: NodeList tableNodes = doc
314: .getElementsByTagName("CLASS");
315: for (int i = 0; i < tableNodes.getLength(); i++) {
316: String tableName = ((Element) tableNodes
317: .item(i)).getAttribute("name");
318: if (tableName.startsWith("root."))
319: tableName = tableName.substring(5,
320: tableName.length());
321: String tableClassName = tableName;
322: //System.out.println("Trying to load class "+tableClassName);
323: Class cls = cl.loadClass(tableClassName);
324: // if this is a cached DO class,
325: // must contain methods getCacheDodsTableName() and refreshCache()
326: // I am searching for these methods, and if there are no
327: // such methods, exception will be thrown, and className
328: // won't be added to the list
329: Method mth;
330: mth = cls.getMethod("refreshCache",
331: new Class[] {});
332: mth = cls.getMethod(
333: "getConfigurationAdministration",
334: new Class[] {});
335: retVal.add(new DOTable(databaseName, cls));
336: }
337: }
338: } else {
339: Enhydra.getLogChannel().write(
340: Logger.DEBUG,
341: "ClassList file "
342: + classListFile.getAbsolutePath()
343: + " don't exist !");
344: }
345:
346: } catch (Throwable e) {
347: // e.printStackTrace();
348: Enhydra
349: .getLogChannel()
350: .write(Logger.DEBUG,
351: "Loading DO classes from class list was unsuccessful!");
352: }
353: return retVal;
354: }
355:
356: /**
357: * Find class names in specified ClassList file and add this classes in cache.
358: * @param classListPath path to ClassList file
359: * @param cl class loader
360: * @return list with loaded classes
361: */
362: public static List getCachedDOClassesFromClassListAsResource(
363: InputStream classListInputStream, ClassLoader cl,
364: String databaseName) {
365: List retVal = new ArrayList();
366: try {
367: DocumentBuilderFactory factory = DocumentBuilderFactory
368: .newInstance();
369: DocumentBuilder builder = factory.newDocumentBuilder();
370: Document doc = builder.parse(classListInputStream);
371: NodeList classesNodes = doc.getElementsByTagName("CLASSES");
372: for (int j = 0; j < classesNodes.getLength(); j++) {
373: Element docClasses = (Element) classesNodes.item(j);
374: String dbName = ((Element) classesNodes.item(j))
375: .getAttribute("databaseName");
376: if (dbName == null || dbName.equals(""))
377: dbName = databaseName;
378: NodeList tableNodes = docClasses
379: .getElementsByTagName("CLASS");
380: for (int i = 0; i < tableNodes.getLength(); i++) {
381: String tableName = ((Element) tableNodes.item(i))
382: .getAttribute("name");
383: if (tableName.startsWith("root."))
384: tableName = tableName.substring(5, tableName
385: .length());
386: String tableClassName = tableName;
387: Class cls = cl.loadClass(tableClassName);
388: // if this is a cached DO class,
389: // must contain methods getCacheDodsTableName() and refreshCache()
390: // I am searching for these methods, and if there are no
391: // such methods, exception will be thrown, and className
392: // won't be added to the list
393: Method mth;
394: mth = cls.getMethod("refreshCache", new Class[] {});
395: mth = cls.getMethod(
396: "getConfigurationAdministration",
397: new Class[] {});
398: retVal.add(new DOTable(dbName, cls));
399: }
400: }
401: } catch (Throwable e) {
402: // e.printStackTrace();
403: Enhydra
404: .getLogChannel()
405: .write(Logger.DEBUG,
406: "Loading DO classes from class list was unsuccessful!");
407: }
408: return retVal;
409: }
410:
411: /**
412: * Returns a List of DODS classes that are cached and are located on given path.
413: */
414: private static List getCachedDOClassesForPath(String classPath,
415: ClassLoader cl, String databaseName) {
416: List cachedDOClasses = new ArrayList();
417: // case of a package contained in a jar file.
418: if (classPath.endsWith(".jar")) {
419: JarFile jfile = null;
420: try {
421: jfile = new JarFile(classPath, false);
422: } catch (Throwable ex) {
423: return cachedDOClasses;
424: }
425: // get all entries
426: Enumeration e = jfile.entries();
427: // loop through entries and find appropriate ones
428: while (e.hasMoreElements()) {
429: try {
430: ZipEntry entry = (ZipEntry) e.nextElement();
431: String entryname = entry.getName();
432: // entry must end with DO.class
433: if (entryname.endsWith("DO.class")) {
434: // removes the .class extension
435: String className = entryname.substring(0,
436: entryname.length() - 6);
437: // removes starting '/'
438: if (className.startsWith("/"))
439: className = className.substring(1);
440: // replacing '/' with '.' (prepearing for loading class)
441: className = className.replace('/', '.');
442:
443: // loading the class
444: //System.out.println("Loading class.."+className);
445: Class cls = cl.loadClass(className);
446: //System.out.println("Class "+cls+" loaded..");
447: // if this is a cached DO class,
448: // must contain methods getCacheDodsTableName() and refreshCache()
449: // I am searching for these methods, and if there are no
450: // such methods, exception will be thrown, and className
451: // won't be added to the list
452: Method mth;
453: //System.out.println("Getting method rc..");
454: mth = cls.getMethod("refreshCache",
455: new Class[] {});
456: //System.out.println("Method rc get..");
457: mth = cls.getMethod(
458: "getConfigurationAdministration",
459: new Class[] {});
460: cachedDOClasses.add(new DOTable(databaseName,
461: cls));
462: }
463: } catch (Throwable thr) {
464: }
465: }
466: } else { // if it is not .jar file, but directory
467: // getting the package folder
468: File startingFolder = new File(classPath);
469: // if folder exists and realy is a folder but not file
470: if (startingFolder.exists() && startingFolder.isDirectory()) {
471: // getting all DO class files within folder
472: Set allDOClassFiles = new HashSet();
473: traverseDOClasses(startingFolder, allDOClassFiles);
474: Iterator files = allDOClassFiles.iterator();
475: while (files.hasNext()) {
476: try {
477: File f = (File) files.next();
478: String fullFileName = f.getAbsolutePath();
479: // removes the .class extension
480: String className = fullFileName.substring(0,
481: fullFileName.length() - 6);
482: // removes the starting folder full name
483: className = className.substring(classPath
484: .length() + 1, className.length());
485: // replacing path separator with '.'
486: className = className.replace(
487: File.separatorChar, '.');
488: // loading the class
489: Class cls = cl.loadClass(className);
490: // if this is a cached DO class,
491: // must contain methods getCacheDodsTableName() and refreshCache()
492: // I am searching for these methods, and if there are no
493: // such methods, exception will be thrown, and className
494: // won't be added to the list
495: Method mth;
496: mth = cls.getMethod("refreshCache",
497: new Class[] {});
498: mth = cls.getMethod(
499: "getConfigurationAdministration",
500: new Class[] {});
501: cachedDOClasses.add(cls);
502: } catch (Throwable thr) {
503: }
504: }
505: }
506: }
507: return cachedDOClasses;
508: }
509:
510: /**
511: * Returns a list of files which names ends with 'DO.class'.
512: * This is a recursive implementation, and search starts from
513: * given folder represented by f.
514: */
515: private static void traverseDOClasses(File f, Collection c) {
516: if (!f.exists()) {
517: // File f doesn't exist");
518: return;
519: }
520: if (f.isDirectory()) {
521: File[] children = f.listFiles(doClassFileFilter);
522: for (int i = 0; i < children.length; i++) {
523: traverseDOClasses(children[i], c);
524: }
525: } else {
526: c.add(f);
527: }
528: }
529:
530: /**
531: * The filter for search on DO classes-searchs for
532: * files ending with 'DO.class'.
533: */
534: private static DOClassFileFilter doClassFileFilter = new DOClassFileFilter();
535:
536: }
537:
538: /**
539: * Class that implements filter that filters folders and
540: * files ending with 'DO.class'.
541: */
542: class DOClassFileFilter implements FileFilter {
543: public boolean accept(File pathname) {
544: return (pathname.isDirectory() || pathname.getName().endsWith(
545: "DO.class"));
546: }
547: }
|