xref: /AOO41X/main/scripting/java/org/openoffice/idesupport/JavaFinder.java (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
1 package org.openoffice.idesupport;
2 
3 import java.io.File;
4 import java.io.IOException;
5 import java.util.ArrayList;
6 import java.util.Enumeration;
7 import java.util.Vector;
8 import java.lang.reflect.Method;
9 import java.lang.reflect.Modifier;
10 import java.net.URL;
11 import java.net.URLClassLoader;
12 import java.net.MalformedURLException;
13 import org.openoffice.idesupport.zip.ParcelZipper;
14 
15 import com.sun.star.script.framework.container.ScriptEntry;
16 
17 public class JavaFinder implements MethodFinder {
18 
19     private static JavaFinder finder;
20     private static final String JAVA_SUFFIX = ".java";
21     private static final String CLASS_SUFFIX = ".class";
22     private static final String LANGUAGE = "Java";
23     private static final String FIRST_PARAM =
24         "drafts.com.sun.star.script.framework.runtime.XScriptContext";
25 
26     private Vector classpath = null;
27 
28     private JavaFinder() {}
29 
30     private JavaFinder(Vector classpath) {
31         this.classpath = classpath;
32     }
33 
34     public static JavaFinder getInstance() {
35         if (finder == null) {
36             synchronized(JavaFinder.class) {
37                 if (finder == null)
38                     finder = new JavaFinder();
39             }
40         }
41         return finder;
42     }
43 
44     public static JavaFinder getInstance(Vector classpath) {
45         return new JavaFinder(classpath);
46     }
47 
48     public ScriptEntry[] findMethods(File basedir) {
49         String parcelName;
50         ArrayList result = new ArrayList(10);
51         ScriptEntry[] empty = new ScriptEntry[0];
52 
53         if (basedir == null || basedir.exists() == false ||
54             basedir.isDirectory() == false)
55             return empty;
56 
57         parcelName = basedir.getName();
58         if (parcelName.equals(ParcelZipper.CONTENTS_DIRNAME))
59             parcelName = basedir.getParentFile().getName();
60 
61         String[] classNames = findClassNames(basedir);
62         if (classNames != null && classNames.length != 0) {
63 
64             ClassLoader classloader;
65 
66             if (classpath == null)
67                 classloader = getClassLoader(basedir);
68             else
69                 classloader = getClassLoader();
70 
71             for (int i = 0; i < classNames.length; i++)
72             {
73                 try
74                 {
75                     Class clazz = classloader.loadClass(classNames[i]);
76                     Method[] methods = clazz.getDeclaredMethods();
77                     for (int k = 0; k < methods.length; k++)
78                     {
79                         if (Modifier.isPublic(methods[k].getModifiers()))
80                         {
81                             Class[] params = methods[k].getParameterTypes();
82                             if(params.length > 0)
83                             {
84                                 if(params[0].getName().equals(FIRST_PARAM))
85                                 {
86                                     ScriptEntry entry =
87                                         new ScriptEntry(classNames[i] + "." +
88                                             methods[k].getName(), parcelName);
89                                     result.add(entry);
90                                 }
91                             }
92                         }
93                     }
94                 }
95                 catch (ClassNotFoundException e)
96                 {
97                     System.err.println("Caught ClassNotFoundException loading: "
98                         + classNames[i]);
99                     continue;
100                 }
101                 catch (NoClassDefFoundError nc)
102                 {
103                     System.err.println("Caught NoClassDefFoundErr loading: " +
104                         classNames[i]);
105                     continue;
106                 }
107             }
108         }
109 
110         if (result.size() != 0)
111             return (ScriptEntry[])result.toArray(empty);
112         return empty;
113     }
114 
115     private ClassLoader getClassLoader() {
116         int len = classpath.size();
117         ArrayList urls = new ArrayList(len);
118 
119         for (int i = 0; i < len; i++) {
120             try {
121                 String s = (String)classpath.elementAt(i);
122                 s = SVersionRCFile.toFileURL(s);
123 
124                 if (s != null)
125                     urls.add(new URL(s));
126             }
127             catch (MalformedURLException mue) {
128             }
129         }
130 
131         return new URLClassLoader((URL[])urls.toArray(new URL[0]));
132     }
133 
134     private ClassLoader getClassLoader(File basedir) {
135         ArrayList files = findFiles(basedir, ".jar");
136         files.add(basedir);
137 
138         try {
139             Enumeration offices = SVersionRCFile.createInstance().getVersions();
140 
141             while (offices.hasMoreElements()) {
142                 OfficeInstallation oi = (OfficeInstallation)offices.nextElement();
143                 String unoil = SVersionRCFile.getPathForUnoil(oi.getPath());
144 
145                 if (unoil != null) {
146                     files.add(new File(unoil, "unoil.jar"));
147                     break;
148                 }
149             }
150         }
151         catch (IOException ioe) {
152             return null;
153         }
154 
155         URL[] urls = new URL[files.size()];
156         String urlpath;
157         File f;
158         for (int i = 0; i < urls.length; i++) {
159             try {
160                 f = (File)files.get(i);
161                 urlpath = SVersionRCFile.toFileURL(f.getAbsolutePath());
162 
163                 if (urlpath != null)
164                     urls[i] = new URL(urlpath);
165             }
166             catch (MalformedURLException mue) {
167                 // do nothing, go on to next file
168             }
169         }
170 
171         return new URLClassLoader(urls);
172     }
173 
174     private ArrayList findFiles(File basedir, String suffix) {
175         ArrayList result = new ArrayList();
176         File[] children = basedir.listFiles();
177 
178         for (int i = 0; i < children.length; i++) {
179             if (children[i].isDirectory())
180                 result.addAll(findFiles(children[i], suffix));
181             else if (children[i].getName().endsWith(suffix))
182                 result.add(children[i]);
183         }
184         return result;
185     }
186 
187     private String[] findClassNames(File basedir)
188     {
189         ArrayList classFiles = findFiles(basedir, CLASS_SUFFIX);
190         if(classFiles == null || classFiles.size() == 0)
191             return null;
192 
193         ArrayList javaFiles = findFiles(basedir, JAVA_SUFFIX);
194         if(javaFiles == null || javaFiles.size() == 0)
195             return null;
196 
197         ArrayList result = new ArrayList();
198         for (int i = 0; i < classFiles.size(); i++)
199         {
200             File classFile = (File)classFiles.get(i);
201             String className = classFile.getName();
202             className = className.substring(0, className.lastIndexOf(CLASS_SUFFIX));
203             boolean finished = false;
204 
205 
206             for (int j = 0; j < javaFiles.size() && finished == false; j++)
207             {
208                 File javaFile = (File)javaFiles.get(j);
209                 String javaName = javaFile.getName();
210                 javaName = javaName.substring(0, javaName.lastIndexOf(JAVA_SUFFIX));
211 
212                 if (javaName.equals(className))
213                 {
214                     String path = classFile.getAbsolutePath();
215                     path = path.substring(basedir.getAbsolutePath().length() + 1);
216                     path = path.replace(File.separatorChar, '.');
217                     path = path.substring(0, path.lastIndexOf(CLASS_SUFFIX));
218 
219                     result.add(path);
220                     javaFiles.remove(j);
221                     finished = true;
222                 }
223             }
224         }
225         return (String[])result.toArray(new String[0]);
226     }
227 }
228