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