LibreOffice Module odk (master) 1
Loader.java
Go to the documentation of this file.
1/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20package com.sun.star.lib.loader;
21
22import java.io.File;
23import java.io.IOException;
24import java.io.InputStream;
25import java.io.UnsupportedEncodingException;
26import java.lang.reflect.Method;
27import java.net.JarURLConnection;
28import java.net.MalformedURLException;
29import java.net.URL;
30import java.net.URLClassLoader;
31import java.util.Enumeration;
32import java.util.jar.Attributes;
33import java.util.jar.Manifest;
34import java.util.StringTokenizer;
35import java.util.ArrayList;
36import java.security.AccessController;
37import java.security.PrivilegedAction;
38
46public final class Loader {
47
48 private static ClassLoader m_Loader = null;
49
53 private Loader() {}
54
62 public static void main( String[] arguments ) throws Exception {
63
64 // get the name of the class to be loaded from the manifest
65 String className = null;
66 Class clazz = Loader.class;
67 ClassLoader loader = clazz.getClassLoader();
68 ArrayList<URL> res = new ArrayList<URL>();
69 try {
70 Enumeration<URL> en = loader.getResources( "META-INF/MANIFEST.MF" );
71 while ( en.hasMoreElements() ) {
72 res.add( en.nextElement() );
73 }
74 // the jarfile with the com/sun/star/lib/loader/Loader.class
75 // per-entry attribute is most probably the last resource in the
76 // list, therefore search backwards
77 for ( int i = res.size() - 1; i >= 0; i-- ) {
78 URL jarurl = res.get( i );
79 try {
80 JarURLConnection jarConnection =
81 (JarURLConnection) jarurl.openConnection();
82 Manifest mf = jarConnection.getManifest();
83 Attributes attrs = (mf != null) ? mf.getAttributes(
84 "com/sun/star/lib/loader/Loader.class") : null;
85 if ( attrs != null ) {
86 className = attrs.getValue( "Application-Class" );
87 if ( className != null )
88 break;
89 }
90 } catch ( IOException e ) {
91 // if an I/O error occurs when opening a new
92 // JarURLConnection, ignore this manifest file
93 System.err.println( "com.sun.star.lib.loader.Loader::" +
94 "main: bad manifest file: " + e );
95 }
96 }
97 } catch ( IOException e ) {
98 // if an I/O error occurs when getting the manifest resources,
99 // try to get the name of the class to be loaded from the argument
100 // list
101 System.err.println( "com.sun.star.lib.loader.Loader::" +
102 "main: cannot get manifest resources: " + e );
103 }
104
105 // if no manifest entry was found, get the name of the class
106 // to be loaded from the argument list
107 String[] args;
108 if ( className == null ) {
109 if ( arguments.length > 0 ) {
110 className = arguments[0];
111 args = new String[arguments.length - 1];
112 System.arraycopy( arguments, 1, args, 0, args.length );
113 } else {
114 throw new IllegalArgumentException(
115 "The name of the class to be loaded must be either " +
116 "specified in the Main-Class attribute of the " +
117 "com/sun/star/lib/loader/Loader.class entry " +
118 "of the manifest file or as a command line argument." );
119 }
120 } else {
121 args = arguments;
122 }
123
124 // load the class with the customized class loader and
125 // invoke the main method
126 if ( className != null ) {
127 ClassLoader cl = getCustomLoader();
128 Thread.currentThread().setContextClassLoader(cl);
129 Class c = cl.loadClass( className );
130 @SuppressWarnings("unchecked")
131 Method m = c.getMethod( "main", new Class[] { String[].class } );
132 m.invoke( null, new Object[] { args } );
133 }
134 }
135
142 public static synchronized ClassLoader getCustomLoader() {
143 if ( m_Loader == null ) {
144
145 // get the urls from which to load classes and resources
146 // from the class path
147 ArrayList<URL> vec = new ArrayList<URL>();
148 String classpath = null;
149 try {
150 classpath = System.getProperty( "java.class.path" );
151 } catch ( SecurityException e ) {
152 // don't add the class path entries to the list of class
153 // loader URLs
154 System.err.println( "com.sun.star.lib.loader.Loader::" +
155 "getCustomLoader: cannot get system property " +
156 "java.class.path: " + e );
157 }
158 if ( classpath != null ) {
159 addUrls(vec, classpath, File.pathSeparator);
160 }
161
162 // get the urls from which to load classes and resources
163 // from the UNO installation
164 String path = InstallationFinder.getPath();
165 if ( path != null ) {
166 callUnoinfo(path, vec);
167 } else {
168 System.err.println( "com.sun.star.lib.loader.Loader::" +
169 "getCustomLoader: no UNO installation found!" );
170 }
171
172 // copy urls to array
173 final URL[] urls = new URL[vec.size()];
174 vec.toArray( urls );
175
176 // instantiate class loader
177 m_Loader = AccessController.doPrivileged(
178 new PrivilegedAction<ClassLoader>() {
179 public ClassLoader run() {
180 return new CustomURLClassLoader(urls);
181 }
182 });
183 }
184
185 return m_Loader;
186 }
187
188 private static void addUrls(ArrayList<URL> urls, String data, String delimiter) {
189 StringTokenizer tokens = new StringTokenizer( data, delimiter );
190 while ( tokens.hasMoreTokens() ) {
191 try {
192 urls.add( new File( tokens.nextToken() ).toURI().toURL() );
193 } catch ( MalformedURLException e ) {
194 // don't add this class path entry to the list of class loader
195 // URLs
196 System.err.println( "com.sun.star.lib.loader.Loader::" +
197 "getCustomLoader: bad pathname: " + e );
198 }
199 }
200 }
201
202 private static void close(InputStream c) {
203 if (c == null) return;
204 try {
205 c.close();
206 } catch (Exception e) {
207 e.printStackTrace();
208 }
209 }
210
211 private static void callUnoinfo(String path, ArrayList<URL> urls) {
212 Process p;
213 try {
214 p = Runtime.getRuntime().exec(
215 new String[] { new File(path, "unoinfo").getPath(), "java" });
216 } catch (IOException e) {
217 System.err.println(
218 "com.sun.star.lib.loader.Loader::getCustomLoader: exec" +
219 " unoinfo: " + e);
220 return;
221 }
222 new Drain(p.getErrorStream()).start();
223 int code;
224 byte[] buf = new byte[1000];
225 int n = 0;
226 InputStream is = null;
227 try {
228 is = p.getInputStream();
229 code = is.read();
230 for (;;) {
231 if (n == buf.length) {
232 if (n > Integer.MAX_VALUE / 2) {
233 System.err.println(
234 "com.sun.star.lib.loader.Loader::getCustomLoader:" +
235 " too much unoinfo output");
236 return;
237 }
238 byte[] buf2 = new byte[2 * n];
239 System.arraycopy(buf, 0, buf2, 0, n);
240 buf = buf2;
241 }
242 int k = is.read(buf, n, buf.length - n);
243 if (k == -1) {
244 break;
245 }
246 n += k;
247 }
248 } catch (IOException e) {
249 System.err.println(
250 "com.sun.star.lib.loader.Loader::getCustomLoader: reading" +
251 " unoinfo output: " + e);
252 return;
253 } finally {
254 close(is);
255 }
256
257 int ev;
258 try {
259 ev = p.waitFor();
260 } catch (InterruptedException e) {
261 Thread.currentThread().interrupt();
262 System.err.println(
263 "com.sun.star.lib.loader.Loader::getCustomLoader: waiting for" +
264 " unoinfo: " + e);
265 return;
266 }
267 if (ev != 0) {
268 System.err.println(
269 "com.sun.star.lib.loader.Loader::getCustomLoader: unoinfo"
270 + " exit value " + n);
271 return;
272 }
273 String s;
274 if (code == '0') {
275 s = new String(buf);
276 } else if (code == '1') {
277 try {
278 s = new String(buf, "UTF-16LE");
279 } catch (UnsupportedEncodingException e) {
280 System.err.println(
281 "com.sun.star.lib.loader.Loader::getCustomLoader:" +
282 " transforming unoinfo output: " + e);
283 return;
284 }
285 } else {
286 System.err.println(
287 "com.sun.star.lib.loader.Loader::getCustomLoader: bad unoinfo"
288 + " output");
289 return;
290 }
291 addUrls(urls, s, "\0");
292 }
293
294 private static final class Drain extends Thread {
295 public Drain(InputStream stream) {
296 super("unoinfo stderr drain");
297 this.stream = stream;
298 }
299
300 @Override
301 public void run() {
302 try {
303 while (stream.read() != -1) {}
304 } catch (IOException e) { /* ignored */ }
305 }
306
307 private final InputStream stream;
308 }
309
314 private static final class CustomURLClassLoader extends URLClassLoader {
315
316 public CustomURLClassLoader( URL[] urls ) {
317 super( urls );
318 }
319
320 @Override
321 protected Class<?> findClass( String name ) throws ClassNotFoundException {
322 // This is only called via this.loadClass -> super.loadClass ->
323 // this.findClass, after this.loadClass has already called
324 // super.findClass, so no need to call super.findClass again:
325 throw new ClassNotFoundException( name );
326 }
327
328 @Override
329 protected synchronized Class<?> loadClass( String name, boolean resolve )
330 throws ClassNotFoundException
331 {
332 Class c = findLoadedClass( name );
333 if ( c == null ) {
334 try {
335 c = super.findClass( name );
336 } catch ( ClassNotFoundException e ) {
337 return super.loadClass( name, resolve );
338 } catch ( SecurityException e ) {
339 // A SecurityException "Prohibited package name: java.lang"
340 // may occur when the user added the JVM's rt.jar to the
341 // java.class.path:
342 return super.loadClass( name, resolve );
343 }
344 }
345 if ( resolve ) {
346 resolveClass( c );
347 }
348 return c;
349 }
350 }
351}
352
353/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
A customized class loader which is used to load classes and resources from a search path of user-defi...
Definition: Loader.java:314
synchronized Class<?> loadClass(String name, boolean resolve)
Definition: Loader.java:329
This class can be used as a loader for application classes which use UNO.
Definition: Loader.java:46
static void callUnoinfo(String path, ArrayList< URL > urls)
Definition: Loader.java:211
static ClassLoader m_Loader
Definition: Loader.java:48
static void main(String[] arguments)
The main method instantiates a customized class loader with the UNO jar files added to the search pat...
Definition: Loader.java:62
static synchronized ClassLoader getCustomLoader()
Gets the customized class loader with the UNO jar files added to the search path.
Definition: Loader.java:142
static void close(InputStream c)
Definition: Loader.java:202
Loader()
do not instantiate
Definition: Loader.java:53
static void addUrls(ArrayList< URL > urls, String data, String delimiter)
Definition: Loader.java:188
const char * name
void * p
sal_Int64 n
def run(arg=None, arg2=-1)
@ Exception
int i
dictionary tokens
m
args
loader
sal_Unicode code
Method