2
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
4
* Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
6
* The contents of this file are subject to the terms of either the GNU
7
* General Public License Version 2 only ("GPL") or the Common
8
* Development and Distribution License("CDDL") (collectively, the
9
* "License"). You may not use this file except in compliance with the
10
* License. You can obtain a copy of the License at
11
* http://www.netbeans.org/cddl-gplv2.html
12
* or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
* specific language governing permissions and limitations under the
14
* License. When distributing the software, include this License Header
15
* Notice in each file and include the License file at
16
* nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
17
* particular file as subject to the "Classpath" exception as provided
18
* by Sun in the GPL Version 2 section of the License file that
19
* accompanied this code. If applicable, add the following below the
20
* License Header, with the fields enclosed by brackets [] replaced by
21
* your own identifying information:
22
* "Portions Copyrighted [year] [name of copyright owner]"
26
* The Original Software is NetBeans. The Initial Developer of the Original
27
* Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
28
* Microsystems, Inc. All Rights Reserved.
30
* If you wish your version of this file to be governed by only the CDDL
31
* or only the GPL Version 2, indicate your decision by adding
32
* "[Contributor] elects to include this software in this distribution
33
* under the [CDDL or GPL Version 2] license." If you do not indicate a
34
* single choice of license, a recipient has the option to distribute
35
* your version of this file under either the CDDL, the GPL Version 2 or
36
* to extend the choice of license to its licensees as provided above.
37
* However, if you add GPL Version 2 code and therefore, elected the GPL
38
* Version 2 license, then the option applies only if the new code is
39
* made subject to such option by the copyright holder.
45
import java.io.IOException;
46
import java.io.InputStream;
47
import java.util.ArrayList;
48
import java.util.Collections;
49
import java.util.Iterator;
50
import java.util.List;
51
import java.util.Locale;
52
import java.util.MissingResourceException;
53
import java.util.Properties;
54
import java.util.ResourceBundle;
56
import java.util.jar.Attributes;
57
import java.util.jar.Manifest;
58
import java.util.logging.Level;
59
import org.openide.util.NbBundle;
61
/** Object representing one module, possibly installed.
62
* Responsible for opening of module JAR file; reading
63
* manifest; parsing basic information such as dependencies;
64
* and creating a classloader for use by the installer.
65
* Methods not defined in ModuleInfo must be called from within
66
* the module manager's read mutex as a rule.
69
final class FixedModule extends Module {
71
/** localized properties, only non-null if requested from disabled module */
72
private Properties localizedProps;
73
private final Manifest manifest;
75
/** Create a special-purpose "fixed" JAR. */
76
public FixedModule(ModuleManager mgr, Events ev, Manifest manifest, Object history, ClassLoader classloader) throws InvalidException {
77
this(mgr, ev, manifest, history, classloader, false, false);
81
* Create a special-purpose "fixed" JAR which may nonetheless be marked eager or autoload.
84
public FixedModule(ModuleManager mgr, Events ev, Manifest manifest, Object history, ClassLoader classloader, boolean autoload, boolean eager) throws InvalidException {
85
super(mgr, ev, history, classloader, autoload, eager);
86
this.manifest = manifest;
87
loadLocalizedPropsClasspath();
91
public @Override Manifest getManifest() {
95
/** Get a localized attribute.
96
* First, if OpenIDE-Module-Localizing-Bundle was given, the specified
97
* bundle file (in all locale JARs as well as base JAR) is searched for
98
* a key of the specified name.
99
* Otherwise, the manifest's main attributes are searched for an attribute
100
* with the specified name, possibly with a locale suffix.
101
* If the attribute name contains a slash, and there is a manifest section
102
* named according to the part before the last slash, then this section's attributes
103
* are searched instead of the main attributes, and for the attribute listed
104
* after the slash. Currently this would only be useful for localized filesystem
105
* names. E.g. you may request the attribute org/foo/MyFileSystem.class/Display-Name.
106
* In the future certain attributes known to be dangerous could be
107
* explicitly suppressed from this list; should only be used for
108
* documented localizable attributes such as OpenIDE-Module-Name etc.
110
public Object getLocalizedAttribute(String attr) {
111
String locb = getManifest().getMainAttributes().getValue("OpenIDE-Module-Localizing-Bundle"); // NOI18N
112
boolean usingLoader = false;
114
if (classloader != null) {
115
if (locb.endsWith(".properties")) { // NOI18N
117
String basename = locb.substring(0, locb.length() - 11).replace('/', '.');
119
ResourceBundle bundle = NbBundle.getBundle(basename, Locale.getDefault(), classloader);
121
return bundle.getString(attr);
122
} catch (MissingResourceException mre) {
125
} catch (MissingResourceException mre) {
126
Util.err.log(Level.WARNING, null, mre);
129
Util.err.warning("cannot efficiently load non-*.properties OpenIDE-Module-Localizing-Bundle: " + locb);
133
if (localizedProps != null) {
134
String val = localizedProps.getProperty(attr);
141
// Try in the manifest now.
142
int idx = attr.lastIndexOf('/'); // NOI18N
144
// Simple main attribute.
145
return NbBundle.getLocalizedValue(getManifest().getMainAttributes(), new Attributes.Name(attr));
147
// Attribute of a manifest section.
148
String section = attr.substring(0, idx);
149
String realAttr = attr.substring(idx + 1);
150
Attributes attrs = getManifest().getAttributes(section);
152
return NbBundle.getLocalizedValue(attrs, new Attributes.Name(realAttr));
159
public boolean isFixed() {
163
/** Similar, but for fixed modules only.
164
* Should be very rarely used: only for classpath modules with a strangely
165
* named OpenIDE-Module-Localizing-Bundle (not *.properties).
167
private void loadLocalizedPropsClasspath() throws InvalidException {
168
Attributes attr = manifest.getMainAttributes();
169
String locbundle = attr.getValue("OpenIDE-Module-Localizing-Bundle"); // NOI18N
170
if (locbundle != null) {
171
Util.err.fine("Localized props in " + locbundle + " for " + attr.getValue("OpenIDE-Module"));
173
int idx = locbundle.lastIndexOf('.'); // NOI18N
179
name = locbundle.substring(0, idx);
180
ext = locbundle.substring(idx);
182
List<String> suffixes = new ArrayList<String>(10);
183
Iterator<String> it = NbBundle.getLocalizingSuffixes();
184
while (it.hasNext()) {
185
suffixes.add(it.next());
187
Collections.reverse(suffixes);
188
for (String suffix: suffixes) {
189
String resource = name + suffix + ext;
190
InputStream is = classloader.getResourceAsStream(resource);
192
Util.err.fine("Found " + resource);
193
if (localizedProps == null) {
194
localizedProps = new Properties();
196
localizedProps.load(is);
199
if (localizedProps == null) {
200
throw new IOException("Could not find localizing bundle: " + locbundle); // NOI18N
202
} catch (IOException ioe) {
203
throw (InvalidException) new InvalidException(ioe.toString()).initCause(ioe);
208
/** Get all JARs loaded by this module.
209
* Includes the module itself, any locale variants of the module,
210
* any extensions specified with Class-Path, any locale variants
211
* of those extensions.
212
* The list will be in classpath order (patches first).
213
* Currently the temp JAR is provided in the case of test modules, to prevent
214
* sporadic ZIP file exceptions when background threads (like Java parsing) tries
215
* to open libraries found in the library path.
216
* JARs already present in the classpath are <em>not</em> listed.
217
* @return a <code>List<File></code> of JARs
219
public List<File> getAllJars() {
220
return Collections.emptyList();
224
* This method can be overriden
225
* in subclasses in case they want to change the reloadable semantix
226
* of the fixed modules.
228
* @throws IllegalStateException as FixedModule cannot be reloaded
230
public void setReloadable(boolean r) {
231
throw new IllegalStateException();
234
/** Reload this module. Access from ModuleManager.
235
* If an exception is thrown, the module is considered
236
* to be in an invalid state.
238
* @throws IllegalStateException as FixedModule cannot be reloaded
240
public void reload() throws IOException {
241
throw new IOException("Fixed module cannot be reloaded!"); // NOI18N
244
// Access from ModuleManager:
245
/** Turn on the classloader. Passed a list of parent modules to use.
246
* The parents should already have had their classloaders initialized.
248
protected void classLoaderUp(Set parents) throws IOException {
252
/** Turn off the classloader and release all resources. */
253
protected void classLoaderDown() {
254
return; // don't touch it
256
/** Should be called after turning off the classloader of one or more modules & GC'ing. */
257
protected void cleanup() {
258
return; // don't touch it
261
/** Notify the module that it is being deleted. */
262
protected void destroy() {
265
/** String representation for debugging. */
266
public @Override String toString() {
267
String s = "FixedModule:" + getCodeNameBase(); // NOI18N
268
if (!isValid()) s += "[invalid]"; // NOI18N