1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 package com.sun.star.comp.loader;
29 
30 import com.sun.star.lib.unoloader.UnoClassLoader;
31 import com.sun.star.lib.util.WeakMap;
32 import java.io.File;
33 import java.io.IOException;
34 import java.net.URL;
35 import java.net.URLClassLoader;
36 import java.util.StringTokenizer;
37 import java.util.jar.Attributes;
38 
39 final class RegistrationClassFinder {
40     public static Class find(String locationUrl)
41         throws ClassNotFoundException, IOException
42     {
43         synchronized (map) {
44             Class c = (Class) WeakMap.getValue(map.get(locationUrl));
45             if (c != null) {
46                 return c;
47             }
48         }
49         URL url = new URL(locationUrl);
50         checkAccess(url);
51         Attributes attr = UnoClassLoader.getJarMainAttributes(url);
52         String name = attr == null
53             ? null : attr.getValue("RegistrationClassName");
54         if (name == null) {
55             return null;
56         }
57         ClassLoader cl1 = RegistrationClassFinder.class.getClassLoader();
58         ClassLoader cl2;
59         if (cl1 instanceof UnoClassLoader) {
60             cl2 = ((UnoClassLoader) cl1).getClassLoader(url, attr);
61         } else {
62             cl2 = URLClassLoader.newInstance(new URL[] { url }, cl1);
63         }
64         Class c = cl2.loadClass(name);
65         synchronized (map) {
66             Class c2 = (Class) WeakMap.getValue(map.get(locationUrl));
67             if (c2 != null) {
68                 return c2;
69             }
70             map.put(locationUrl, c);
71         }
72         return c;
73     }
74 
75     private RegistrationClassFinder() {} // do not instantiate
76 
77     private static void checkAccess(URL url) throws ClassNotFoundException {
78         // The system property com.sun.star.comp.loader.CPLD_ACCESSPATH was
79         // introduced as a hack to restrict which UNO components can be
80         // instantiated.  It seems to be unused nowadays, and should probably be
81         // replaced by the native Java security features, anyway.
82         if (accessPath != null) {
83             if (!url.getProtocol().equals("file")) {
84                 throw new ClassNotFoundException(
85                     "Access restriction: <" + url + "> is not a file URL");
86             }
87             String p;
88             try {
89                 p = new File(url.getFile()).getCanonicalPath();
90             } catch (IOException e) {
91                 throw new ClassNotFoundException(
92                     "Access restriction: <" + url + "> is bad: " + e);
93             }
94             for (int i = 0; i < accessPath.length; ++i) {
95                 String p2 = accessPath[i];
96                 if (p.startsWith(p2) && p.length() > p2.length()
97                     && (p2.charAt(p2.length() - 1) == File.separatorChar
98                         || p.charAt(p2.length()) == File.separatorChar))
99                 {
100                     return;
101                 }
102             }
103             throw new ClassNotFoundException(
104                 "Access restriction: <" + url + "> is restricted");
105         }
106     }
107 
108     private static final WeakMap map = new WeakMap();
109 
110     private static final String[] accessPath;
111     static {
112         String[] ap = null;
113         String p = System.getProperty(
114             "com.sun.star.comp.loader.CPLD_ACCESSPATH");
115         if (p != null) {
116             StringTokenizer t = new StringTokenizer(p, ";");
117             ap = new String[t.countTokens()];
118             int i = 0;
119             while (t.hasMoreTokens()) {
120                 try {
121                     ap[i] = new File(t.nextToken()).getCanonicalPath();
122                     ++i;
123                 } catch (IOException e) {}
124             }
125             if (i != ap.length) {
126                 String[] ap2 = new String[i];
127                 System.arraycopy(ap, 0, ap2, 0, i);
128                 ap = ap2;
129             }
130         }
131         accessPath = ap;
132     }
133 }
134