01: /**
02: * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
03: */package net.sourceforge.pmd.cpd;
04:
05: import java.util.Properties;
06:
07: public class LanguageFactory {
08:
09: public static String[] supportedLanguages = new String[] { "java",
10: "jsp", "cpp", "c", "php", "ruby", "fortran" };
11: private static final String SUFFIX = "Language";
12: public static final String EXTENSION = "extension";
13: public static final String BY_EXTENSION = "by_extension";
14: private static final String PACKAGE = "net.sourceforge.pmd.cpd.";
15:
16: public Language createLanguage(String language) {
17: return createLanguage(language, new Properties());
18: }
19:
20: public Language createLanguage(String language,
21: Properties properties) {
22: language = this .languageAliases(language);
23: // First, we look for a parser following this syntax 'RubyLanguage'
24: Language implementation;
25: try {
26: implementation = this
27: .dynamicLanguageImplementationLoad(this
28: .languageConventionSyntax(language));
29: if (implementation == null) {
30: // if it failed, we look for a parser following this syntax 'CPPLanguage'
31: implementation = this
32: .dynamicLanguageImplementationLoad(language
33: .toUpperCase());
34: //TODO: Should we try to break the coupling with PACKAGE by try to load the class
35: // based on her sole name ?
36: if (implementation == null) {
37: // No proper implementation
38: // FIXME: We should log a warning, shouldn't we ?
39: return new AnyLanguage(language);
40: }
41: }
42: return implementation;
43: } catch (InstantiationException e) {
44: e.printStackTrace();
45: } catch (IllegalAccessException e) {
46: e.printStackTrace();
47: }
48: return null;
49: }
50:
51: private String languageAliases(String language) {
52: // CPD and C language share the same parser
53: if ("c".equals(language))
54: return "cpp";
55: return language;
56: }
57:
58: private Language dynamicLanguageImplementationLoad(String language)
59: throws InstantiationException, IllegalAccessException {
60: try {
61: return (Language) this .getClass().getClassLoader()
62: .loadClass(PACKAGE + language + SUFFIX)
63: .newInstance();
64: } catch (ClassNotFoundException e) {
65: // No class found, returning default implementation
66: // FIXME: There should be somekind of log of this
67: return null;
68: } catch (NoClassDefFoundError e) {
69: // Windows is case insensitive, so it may find the file, even though
70: // the name has a different case. Since Java is case sensitive, it
71: // will not accept the classname inside the file that was found and
72: // will throw a NoClassDefFoundError
73: return null;
74: }
75: }
76:
77: /*
78: * This method does simply this:
79: * ruby -> Ruby
80: * fortran -> Fortran
81: * ...
82: */
83: private String languageConventionSyntax(String language) {
84: return (language.charAt(0) + "").toUpperCase()
85: + language.substring(1, language.length())
86: .toLowerCase();
87: }
88: }
|