1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 package org.openoffice.idesupport;
23 
24 import java.io.File;
25 import java.io.IOException;
26 import java.util.ArrayList;
27 import java.util.Enumeration;
28 import java.util.Vector;
29 import java.lang.reflect.Method;
30 import java.lang.reflect.Modifier;
31 import java.net.URL;
32 import java.net.URLClassLoader;
33 import java.net.MalformedURLException;
34 import org.openoffice.idesupport.zip.ParcelZipper;
35 
36 import com.sun.star.script.framework.container.ScriptEntry;
37 
38 public class JavaFinder implements MethodFinder {
39 
40     private static JavaFinder finder;
41     private static final String JAVA_SUFFIX = ".java";
42     private static final String CLASS_SUFFIX = ".class";
43     private static final String LANGUAGE = "Java";
44     private static final String FIRST_PARAM =
45         "drafts.com.sun.star.script.framework.runtime.XScriptContext";
46 
47     private Vector classpath = null;
48 
JavaFinder()49     private JavaFinder() {}
50 
JavaFinder(Vector classpath)51     private JavaFinder(Vector classpath) {
52         this.classpath = classpath;
53     }
54 
getInstance()55     public static JavaFinder getInstance() {
56         if (finder == null) {
57             synchronized(JavaFinder.class) {
58                 if (finder == null)
59                     finder = new JavaFinder();
60             }
61         }
62         return finder;
63     }
64 
getInstance(Vector classpath)65     public static JavaFinder getInstance(Vector classpath) {
66         return new JavaFinder(classpath);
67     }
68 
findMethods(File basedir)69     public ScriptEntry[] findMethods(File basedir) {
70         String parcelName;
71         ArrayList result = new ArrayList(10);
72         ScriptEntry[] empty = new ScriptEntry[0];
73 
74         if (basedir == null || basedir.exists() == false ||
75             basedir.isDirectory() == false)
76             return empty;
77 
78         parcelName = basedir.getName();
79         if (parcelName.equals(ParcelZipper.CONTENTS_DIRNAME))
80             parcelName = basedir.getParentFile().getName();
81 
82         String[] classNames = findClassNames(basedir);
83         if (classNames != null && classNames.length != 0) {
84 
85             ClassLoader classloader;
86 
87             if (classpath == null)
88                 classloader = getClassLoader(basedir);
89             else
90                 classloader = getClassLoader();
91 
92             for (int i = 0; i < classNames.length; i++)
93             {
94                 try
95                 {
96                     Class clazz = classloader.loadClass(classNames[i]);
97                     Method[] methods = clazz.getDeclaredMethods();
98                     for (int k = 0; k < methods.length; k++)
99                     {
100                         if (Modifier.isPublic(methods[k].getModifiers()))
101                         {
102                             Class[] params = methods[k].getParameterTypes();
103                             if(params.length > 0)
104                             {
105                                 if(params[0].getName().equals(FIRST_PARAM))
106                                 {
107                                     ScriptEntry entry =
108                                         new ScriptEntry(classNames[i] + "." +
109                                             methods[k].getName(), parcelName);
110                                     result.add(entry);
111                                 }
112                             }
113                         }
114                     }
115                 }
116                 catch (ClassNotFoundException e)
117                 {
118                     System.err.println("Caught ClassNotFoundException loading: "
119                         + classNames[i]);
120                     continue;
121                 }
122                 catch (NoClassDefFoundError nc)
123                 {
124                     System.err.println("Caught NoClassDefFoundErr loading: " +
125                         classNames[i]);
126                     continue;
127                 }
128             }
129         }
130 
131         if (result.size() != 0)
132             return (ScriptEntry[])result.toArray(empty);
133         return empty;
134     }
135 
getClassLoader()136     private ClassLoader getClassLoader() {
137         int len = classpath.size();
138         ArrayList urls = new ArrayList(len);
139 
140         for (int i = 0; i < len; i++) {
141             try {
142                 String s = (String)classpath.elementAt(i);
143                 s = SVersionRCFile.toFileURL(s);
144 
145                 if (s != null)
146                     urls.add(new URL(s));
147             }
148             catch (MalformedURLException mue) {
149             }
150         }
151 
152         return new URLClassLoader((URL[])urls.toArray(new URL[0]));
153     }
154 
getClassLoader(File basedir)155     private ClassLoader getClassLoader(File basedir) {
156         ArrayList files = findFiles(basedir, ".jar");
157         files.add(basedir);
158 
159         try {
160             Enumeration offices = SVersionRCFile.createInstance().getVersions();
161 
162             while (offices.hasMoreElements()) {
163                 OfficeInstallation oi = (OfficeInstallation)offices.nextElement();
164                 String unoil = SVersionRCFile.getPathForUnoil(oi.getPath());
165 
166                 if (unoil != null) {
167                     files.add(new File(unoil, "unoil.jar"));
168                     break;
169                 }
170             }
171         }
172         catch (IOException ioe) {
173             return null;
174         }
175 
176         URL[] urls = new URL[files.size()];
177         String urlpath;
178         File f;
179         for (int i = 0; i < urls.length; i++) {
180             try {
181                 f = (File)files.get(i);
182                 urlpath = SVersionRCFile.toFileURL(f.getAbsolutePath());
183 
184                 if (urlpath != null)
185                     urls[i] = new URL(urlpath);
186             }
187             catch (MalformedURLException mue) {
188                 // do nothing, go on to next file
189             }
190         }
191 
192         return new URLClassLoader(urls);
193     }
194 
findFiles(File basedir, String suffix)195     private ArrayList findFiles(File basedir, String suffix) {
196         ArrayList result = new ArrayList();
197         File[] children = basedir.listFiles();
198 
199         for (int i = 0; i < children.length; i++) {
200             if (children[i].isDirectory())
201                 result.addAll(findFiles(children[i], suffix));
202             else if (children[i].getName().endsWith(suffix))
203                 result.add(children[i]);
204         }
205         return result;
206     }
207 
findClassNames(File basedir)208     private String[] findClassNames(File basedir)
209     {
210         ArrayList classFiles = findFiles(basedir, CLASS_SUFFIX);
211         if(classFiles == null || classFiles.size() == 0)
212             return null;
213 
214         ArrayList javaFiles = findFiles(basedir, JAVA_SUFFIX);
215         if(javaFiles == null || javaFiles.size() == 0)
216             return null;
217 
218         ArrayList result = new ArrayList();
219         for (int i = 0; i < classFiles.size(); i++)
220         {
221             File classFile = (File)classFiles.get(i);
222             String className = classFile.getName();
223             className = className.substring(0, className.lastIndexOf(CLASS_SUFFIX));
224             boolean finished = false;
225 
226 
227             for (int j = 0; j < javaFiles.size() && finished == false; j++)
228             {
229                 File javaFile = (File)javaFiles.get(j);
230                 String javaName = javaFile.getName();
231                 javaName = javaName.substring(0, javaName.lastIndexOf(JAVA_SUFFIX));
232 
233                 if (javaName.equals(className))
234                 {
235                     String path = classFile.getAbsolutePath();
236                     path = path.substring(basedir.getAbsolutePath().length() + 1);
237                     path = path.replace(File.separatorChar, '.');
238                     path = path.substring(0, path.lastIndexOf(CLASS_SUFFIX));
239 
240                     result.add(path);
241                     javaFiles.remove(j);
242                     finished = true;
243                 }
244             }
245         }
246         return (String[])result.toArray(new String[0]);
247     }
248 }
249