2 * Copyright 2000-2009 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package com
.intellij
.uiDesigner
;
18 import com
.intellij
.ProjectTopics
;
19 import com
.intellij
.openapi
.Disposable
;
20 import com
.intellij
.openapi
.components
.ServiceManager
;
21 import com
.intellij
.openapi
.module
.Module
;
22 import com
.intellij
.openapi
.module
.ModuleUtil
;
23 import com
.intellij
.openapi
.project
.Project
;
24 import com
.intellij
.openapi
.roots
.ModuleRootEvent
;
25 import com
.intellij
.openapi
.roots
.ModuleRootListener
;
26 import com
.intellij
.openapi
.roots
.ProjectRootsTraversing
;
27 import com
.intellij
.openapi
.roots
.ProjectClasspathTraversing
;
28 import com
.intellij
.openapi
.util
.Disposer
;
29 import com
.intellij
.openapi
.vfs
.VirtualFile
;
30 import com
.intellij
.uiDesigner
.core
.Spacer
;
31 import com
.intellij
.util
.PathUtil
;
32 import com
.intellij
.util
.lang
.UrlClassLoader
;
33 import com
.intellij
.util
.messages
.MessageBusConnection
;
34 import org
.jetbrains
.annotations
.NotNull
;
38 import java
.net
.MalformedURLException
;
43 * @author Anton Katilin
44 * @author Vladimir Kondratyev
46 public final class LoaderFactory
{
47 private final Project myProject
;
49 private final WeakHashMap
<Module
, ClassLoader
> myModule2ClassLoader
;
50 private ClassLoader myProjectClassLoader
= null;
51 private final MessageBusConnection myConnection
;
53 public static LoaderFactory
getInstance(final Project project
) {
54 return ServiceManager
.getService(project
, LoaderFactory
.class);
57 public LoaderFactory(final Project project
) {
59 myModule2ClassLoader
= new WeakHashMap
<Module
, ClassLoader
>();
60 myConnection
= myProject
.getMessageBus().connect();
61 myConnection
.subscribe(ProjectTopics
.PROJECT_ROOTS
, new ModuleRootListener() {
62 public void beforeRootsChange(final ModuleRootEvent event
) {}
63 public void rootsChanged(final ModuleRootEvent event
) {
64 clearClassLoaderCache();
68 Disposer
.register(project
, new Disposable() {
69 public void dispose() {
70 myConnection
.disconnect();
71 myModule2ClassLoader
.clear();
76 @NotNull public ClassLoader
getLoader(final VirtualFile formFile
) {
77 final Module module
= ModuleUtil
.findModuleForFile(formFile
, myProject
);
79 return getClass().getClassLoader();
82 return getLoader(module
);
85 public ClassLoader
getLoader(final Module module
) {
86 final ClassLoader cachedLoader
= myModule2ClassLoader
.get(module
);
87 if (cachedLoader
!= null) {
91 final String runClasspath
= ProjectRootsTraversing
.collectRoots(module
, ProjectClasspathTraversing
.FULL_CLASSPATH_RECURSIVE
).getPathsString();
93 final ClassLoader classLoader
= createClassLoader(runClasspath
);
95 myModule2ClassLoader
.put(module
, classLoader
);
100 @NotNull public ClassLoader
getProjectClassLoader() {
101 if (myProjectClassLoader
== null) {
102 final String runClasspath
= ProjectRootsTraversing
.collectRoots(myProject
, ProjectClasspathTraversing
.FULL_CLASSPATH_RECURSIVE
).getPathsString();
103 myProjectClassLoader
= createClassLoader(runClasspath
);
105 return myProjectClassLoader
;
108 private static ClassLoader
createClassLoader(final String runClasspath
) {
109 final ArrayList
<URL
> urls
= new ArrayList
<URL
>();
110 final StringTokenizer tokenizer
= new StringTokenizer(runClasspath
, File
.pathSeparator
);
111 while (tokenizer
.hasMoreTokens()) {
112 final String s
= tokenizer
.nextToken();
114 urls
.add(new File(s
).toURI().toURL());
116 catch (Exception e
) {
122 urls
.add(new File(PathUtil
.getJarPathForClass(Spacer
.class)).toURI().toURL());
124 catch (MalformedURLException ignored
) {
128 final URL
[] _urls
= urls
.toArray(new URL
[urls
.size()]);
129 return new DesignTimeClassLoader(Arrays
.asList(_urls
), null);
132 public void clearClassLoaderCache() {
133 // clear classes with invalid classloader from UIManager cache
134 final UIDefaults uiDefaults
= UIManager
.getDefaults();
135 for (Iterator it
= uiDefaults
.keySet().iterator(); it
.hasNext();) {
136 Object key
= it
.next();
137 Object value
= uiDefaults
.get(key
);
138 if (value
instanceof Class
) {
139 ClassLoader loader
= ((Class
)value
).getClassLoader();
140 if (loader
instanceof DesignTimeClassLoader
) {
145 myModule2ClassLoader
.clear();
146 myProjectClassLoader
= null;
149 private static class DesignTimeClassLoader
extends UrlClassLoader
{
150 public DesignTimeClassLoader(final List
<URL
> urls
, final ClassLoader parent
) {