View Javadoc

1   /*******************************************************************************
2    * SAT4J: a SATisfiability library for Java Copyright (C) 2004, 2012 Artois University and CNRS
3    *
4    * All rights reserved. This program and the accompanying materials
5    * are made available under the terms of the Eclipse Public License v1.0
6    * which accompanies this distribution, and is available at
7    *  http://www.eclipse.org/legal/epl-v10.html
8    *
9    * Alternatively, the contents of this file may be used under the terms of
10   * either the GNU Lesser General Public License Version 2.1 or later (the
11   * "LGPL"), in which case the provisions of the LGPL are applicable instead
12   * of those above. If you wish to allow use of your version of this file only
13   * under the terms of the LGPL, and not to allow others to use your version of
14   * this file under the terms of the EPL, indicate your decision by deleting
15   * the provisions above and replace them with the notice and other provisions
16   * required by the LGPL. If you do not delete the provisions above, a recipient
17   * may use your version of this file under the terms of the EPL or the LGPL.
18   *
19   * Based on the original MiniSat specification from:
20   *
21   * An extensible SAT solver. Niklas Een and Niklas Sorensson. Proceedings of the
22   * Sixth International Conference on Theory and Applications of Satisfiability
23   * Testing, LNCS 2919, pp 502-518, 2003.
24   *
25   * See www.minisat.se for the original solver in C++.
26   *
27   * That class was initially written in 2001 by Daniel Le Berre for JavaWorld JavaTips 113.
28   * http://www.javaworld.com/javaworld/javatips/jw-javatip113.html
29   * 
30   * Contributors:
31   *   CRIL - initial API and implementation
32   *******************************************************************************/
33  package org.sat4j.sat;
34  
35  import java.io.File;
36  import java.io.FilenameFilter;
37  import java.io.IOException;
38  import java.lang.reflect.Modifier;
39  import java.net.JarURLConnection;
40  import java.net.URL;
41  import java.util.Enumeration;
42  import java.util.HashSet;
43  import java.util.Set;
44  import java.util.Vector;
45  import java.util.jar.JarEntry;
46  import java.util.jar.JarFile;
47  import java.util.zip.ZipEntry;
48  
49  /**
50   * 
51   * This class allows dynamic search for classes.
52   * 
53   * @author sroussel and dleberre
54   * 
55   */
56  public class RTSI {
57  
58      public static Vector<String> alreadySeenPckges;
59  
60      public static Vector<String> find(String tosubclassname) {
61          alreadySeenPckges = new Vector<String>();
62          Set<String> v = new HashSet<String>();
63          Set<String> tmp;
64          try {
65              // ClassLoader.getSystemClassLoader().setPackageAssertionStatus("org.sat4j",
66              // true);
67              Class<?> tosubclass = Class.forName(tosubclassname);
68              Package[] pcks = Package.getPackages();
69              for (Package pck : pcks) {
70                  tmp = find(pck.getName(), tosubclass);
71                  if (tmp != null) {
72                      v.addAll(tmp);
73                  }
74              }
75          } catch (ClassNotFoundException ex) {
76              System.err.println("Class " + tosubclassname + " not found!");
77          }
78          return new Vector<String>(v);
79      }
80  
81      public static Set<String> find(String pckname, String tosubclassname) {
82          Set<String> v = new HashSet<String>();
83          try {
84              Class<?> tosubclass = Class.forName(tosubclassname);
85              v = find(pckname, tosubclass);
86          } catch (ClassNotFoundException ex) {
87              System.err.println("Class " + tosubclassname + " not found!");
88          }
89          return v;
90      }
91  
92      public static Set<String> find(String pckgname, Class<?> tosubclass) {
93          if (alreadySeenPckges.contains(pckgname)) {
94              return new HashSet<String>();
95          } else {
96              alreadySeenPckges.add(pckgname);
97              return findnames(pckgname, tosubclass);
98          }
99      }
100 
101     public static Set<String> findnames(String pckgname, Class<?> tosubclass) {
102         Set<String> v = new HashSet<String>();
103         // Code from JWhich
104         // ======
105         // Translate the package name into an absolute path
106         String name = new String(pckgname);
107         if (!name.startsWith("/")) {
108             name = "/" + name;
109         }
110         name = name.replace('.', '/');
111 
112         // Get a File object for the package
113         URL url = RTSI.class.getResource(name);
114         // URL url = tosubclass.getResource(name);
115         // URL url = ClassLoader.getSystemClassLoader().getResource(name);
116         // System.out.println(name+"->"+url);
117 
118         // Happens only if the jar file is not well constructed, i.e.
119         // if the directories do not appear alone in the jar file like here:
120         //
121         // meta-inf/
122         // meta-inf/manifest.mf
123         // commands/ <== IMPORTANT
124         // commands/Command.class
125         // commands/DoorClose.class
126         // commands/DoorLock.class
127         // commands/DoorOpen.class
128         // commands/LightOff.class
129         // commands/LightOn.class
130         // RTSI.class
131         //
132         if (url == null) {
133             return null;
134         }
135 
136         File directory = new File(url.getFile());
137 
138         // New code
139         // ======
140         if (directory.exists()) {
141             // Get the list of the files contained in the package
142             String[] files = directory.list();
143             for (String file : files) {
144 
145                 // we are only interested in .class files
146                 if (file.endsWith(".class")) {
147                     // removes the .class extension
148                     String classname = file.substring(0, file.length() - 6);
149                     try {
150                         // Try to create an instance of the object
151                         Class<?> o = Class.forName(pckgname + "." + classname);
152 
153                         if (tosubclass.isAssignableFrom(o) && !o.isInterface()
154                                 && !Modifier.isAbstract(o.getModifiers())) {
155                             // System.out.println(classname);
156                             v.add(classname);
157                         }
158                     } catch (NoClassDefFoundError cnfex) {
159                         // System.out.println("Warning : no classDefFoundError : "
160                         // + classname);
161                     } catch (ClassNotFoundException cnfex) {
162                         System.err.println(cnfex);
163                     }
164                     // catch (InstantiationException iex) {
165                     // // We try to instanciate an interface
166                     // // or an object that does not have a
167                     // // default constructor
168                     // } catch (IllegalAccessException iaex) {
169                     // // The class is not public
170                     // }
171                 }
172             }
173             File[] dirs = directory.listFiles(new FilenameFilter() {
174                 public boolean accept(File dir, String name) {
175                     return new File(dir.getAbsolutePath() + "/" + name)
176                             .isDirectory();
177                 }
178             });
179             Set<String> tmp;
180             for (File dir : dirs) {
181                 String newName = pckgname + "." + dir.getName();
182                 tmp = find(newName, tosubclass);
183                 if (tmp != null) {
184                     v.addAll(tmp);
185                 }
186 
187             }
188 
189         } else {
190             try {
191                 // It does not work with the filesystem: we must
192                 // be in the case of a package contained in a jar file.
193                 JarURLConnection conn = (JarURLConnection) url.openConnection();
194                 String starts = conn.getEntryName();
195                 JarFile jfile = conn.getJarFile();
196                 Enumeration<JarEntry> e = jfile.entries();
197                 while (e.hasMoreElements()) {
198                     ZipEntry entry = e.nextElement();
199                     String entryname = entry.getName();
200                     if (entryname.startsWith(starts)
201                     // &&(entryname.lastIndexOf('/')<=starts.length())
202                             && entryname.endsWith(".class")) {
203                         String classname = entryname.substring(0,
204                                 entryname.length() - 6);
205                         // System.out.println(classname);
206                         if (classname.startsWith("/")) {
207                             classname = classname.substring(1);
208                         }
209                         classname = classname.replace('/', '.');
210                         try {
211                             // Try to create an instance of the object
212                             // Object o =
213                             // Class.forName(classname).newInstance();
214                             // if (tosubclass.isInstance(o)) {
215 
216                             Class<?> o = Class.forName(classname);
217 
218                             if (tosubclass.isAssignableFrom(o)
219                                     && !o.isInterface()
220                                     && !Modifier.isAbstract(o.getModifiers())) {
221                                 // System.out.println(classname.substring(classname.lastIndexOf('.')+1));
222                                 v.add(classname.substring(classname
223                                         .lastIndexOf('.') + 1));
224                             }
225                         } catch (NoClassDefFoundError cnfex) {
226                             // System.out.println("Warning : no classDefFoundError : "
227                             // + classname);
228                         } catch (ClassNotFoundException cnfex) {
229                             System.err.print(cnfex);
230                         }
231                         // catch (InstantiationException iex) {
232                         // // We try to instanciate an interface
233                         // // or an object that does not have a
234                         // // default constructor
235                         // } catch (IllegalAccessException iaex) {
236                         // // The class is not public
237                         // }
238                     }
239                 }
240             } catch (IOException ioex) {
241                 System.err.println(ioex);
242             }
243         }
244 
245         return v;
246     }
247 
248     public static void displayResultOfFind(String tosubclassname) {
249         System.out.println(find(tosubclassname));
250     }
251 
252     public static void displayResultOfFind(String pckname, String tosubclassname) {
253         System.out.println(find(pckname, tosubclassname));
254     }
255 
256     public static void displayResultOfFind(String pckgname, Class<?> tosubclass) {
257         System.out.println(findnames(pckgname, tosubclass));
258 
259     }
260 
261     public static void main(String[] args) {
262         if (args.length == 2) {
263             displayResultOfFind(args[0], args[1]);
264         } else {
265             if (args.length == 1) {
266                 displayResultOfFind(args[0]);
267             } else {
268                 System.out.println("Usage: java RTSI [<package>] <subclass>");
269             }
270         }
271     }
272 }// RTSI