View Javadoc

1   /**
2    * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
3    */
4   package net.sourceforge.pmd.cpd;
5   
6   import java.util.Properties;
7   
8   public class LanguageFactory {
9   
10     public static String[] supportedLanguages = new String[]{"java", "jsp", "cpp", "c", "php", "ruby","fortran", "ecmascript","cs" };
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         return language;
55       }
56  
57      private Language dynamicLanguageImplementationLoad(String language) throws InstantiationException, IllegalAccessException
58      {
59          try {
60              return (Language) this.getClass().getClassLoader().loadClass(
61                  PACKAGE + language + SUFFIX).newInstance();
62          } catch (ClassNotFoundException e) {
63              // No class found, returning default implementation
64              // FIXME: There should be somekind of log of this
65              return null;
66          } catch (NoClassDefFoundError e) {
67              // Windows is case insensitive, so it may find the file, even though
68              // the name has a different case. Since Java is case sensitive, it
69              // will not accept the classname inside the file that was found and
70              // will throw a NoClassDefFoundError
71              return null;
72          }
73      }
74  
75     /*
76      * This method does simply this:
77      * ruby -> Ruby
78      * fortran -> Fortran
79      * ...
80      */
81     private String languageConventionSyntax(String language) {
82         return (language.charAt(0) + "").toUpperCase() + language.substring(1, language.length()).toLowerCase();
83      }
84  }