All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.openide.modules.InstalledFileLocator Maven / Gradle / Ivy

There is a newer version: RELEASE240
Show newest version
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package org.openide.modules;

import java.io.File;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.Set;
import org.openide.util.Lookup;
import org.openide.util.LookupEvent;
import org.openide.util.LookupListener;

/**
 * Service providing the ability to locate a module-installed file in
 * the NetBeans application's installation.
 * Zero or more instances may be registered to lookup.
 * 

For use in declarative formats, or from APIs which require URLs, * there is a matching URL protocol {@code nbinst}. The host field (optional but * recommended) should be the code name base of the module owning the file; the * path is then relative to that module's cluster. For example, * {@code nbinst://my.module/docs/README} should refer to the file found by * {@code InstalledFileLocator.getDefault().locate("docs/README", "my.module", false)}.

* @author Jesse Glick * @since 3.21 */ public abstract class InstalledFileLocator { private static final InstalledFileLocator DEFAULT = new InstalledFileLocator() { public @Override File locate(String rp, String cnb, boolean l) { InstalledFileLocator[] ifls = getInstances(); for (int i = 0; i < ifls.length; i++) { File f = ifls[i].locate(rp, cnb, l); if (f != null) { return f; } } return null; } public @Override Set locateAll(String relativePath, String codeNameBase, boolean localized) { Set result = null; for (InstalledFileLocator ifl : getInstances()) { Set added = ifl.locateAll(relativePath, codeNameBase, localized); // avoid allocating extra lists, under the assumption there is only one result: if (!added.isEmpty()) { if (result == null) { result = added; } else { result = new LinkedHashSet(result); result.addAll(added); } } } return result != null ? result : Collections.emptySet(); } }; private static InstalledFileLocator[] instances = null; private static Lookup.Result result = null; /** * Used just for guarding direct access to {@link #instances} and {@link #result}. * Should not call foreign code while holding this. * Cf. comments in #64710. */ @SuppressWarnings("RedundantStringConstructorCall") private static final Object LOCK = new String(InstalledFileLocator.class.getName()); /** * No-op constructor for use by subclasses. */ protected InstalledFileLocator() { } /** * Try to locate a file. *
*

* When using the normal NetBeans installation structure and NBM file format, * this path will be relative to the installation directory (or user directory, * for a locally installed module). Other possible installation mechanisms, such * as JNLP (Java WebStart), might arrange the physical files differently, but * generally the path indicated by a module's normal NBM file (beneath netbeans/ * in the NBM) should be interpreted by the locator implementation to point to the actual * location of the file, so the module need not be aware of such details. Some * locator implementations may perform the search more accurately or quickly * when given a code name base for the module that supplies the file. *

*

* The file may refer to a directory (no trailing slash!), in which case the locator * should attempt to find that directory in the installation. Note that only one * file may be located from a given path, so generally this method will not be * useful where a directory can contain many items that may be merged between e.g. * the installation and user directories. For example, the docs folder * (used e.g. for Javadoc) might contain several ZIP files in both the installation and * user areas. Use {@link #locateAll} if you need all results. The module may assume * that all contained files are in the same relative structure in the directory as in * the normal NBM-based installation; unusual locator implementations may need to create * temporary directories with matching structures to return from this method, in case the * physical file locations are not in such a directory structure. * See issue #36701 for details. *

*
*

* Localized and branded lookups should follow the normal naming conventions, * e.g. docs/OpenAPIs_ja.zip would be used for Japanese Javadoc * and locate("docs/OpenAPIs.zip", …, true) * would find it when running in Japanese locale. *

*
*

* For cases where the search is for a module JAR or one of its extensions, client * code may prefer to use the code source given by a class loader. This will permit * a client to find the base URL (may or may not refer to a file) responsible for loading * the contents of the protection domain, typically a JAR file, containing a class * which is accessible to the module class loader. For example: *

*
     Class c = ClassMyModuleDefines.class;
     URL u = c.getProtectionDomain().getCodeSource().getLocation();
     * 
*

* When running from a JAR file, this will typically give e.g. * file:/path/to/archive.jar. This information may be useful, * but it is not conclusive, since there is no guarantee what the URL protocol * will be, nor that the returned URL uniquely identifies a JAR shipped with * the module in its canonical NBM format. InstalledFileLocator * provides stronger guarantees than this technique, since you can explicitly * name a JAR file to be located on disk. *

*
*
*

* This class should not be used just to find resources on the system * filesystem, which in the normal NetBeans installation structure means the * result of merging ${netbeans.home}/system/ with ${netbeans.user}/system/ * as well as module layers and perhaps project-specific storage. To find data in * the system filesystem, use the Filesystems API, e.g. in your layer you can predefine: *

     <filesystem>
     <folder name="MyModule">
     <file name="data.xml" url="contents-in-module-jar.xml"/>
     </folder>
     </filesystem>
     
*

* Then in your code use: *

     String path = "MyModule/data.xml";
     FileObject fo = FileUtil.getConfigFile(path);
     if (fo != null) {
     // use fo.getInputStream() etc.
         // FileUtil.toFile(fo) will often be null, do not rely on it!
     }
     
*
* @param relativePath path from install root, e.g. docs/OpenAPIs.zip * or modules/ext/somelib.jar * (always using / as a separator, regardless of platform) * @param codeNameBase name of the supplying module, e.g. org.netbeans.modules.foo; * may be null if unknown * @param localized true to perform a localized and branded lookup (useful for documentation etc.) * @return the requested File, if it can be found, else null */ public abstract File locate(String relativePath, String codeNameBase, boolean localized); /** * Similar to {@link #locate} but can return multiple results. * The default implementation returns a list with zero or one elements according to {@link #locate}. * @param relativePath a path from install root * @param codeNameBase name of the supplying module or null * @param localized true to perform a localized/branded search * @return a (possibly empty) set of files * @since org.openide.modules 7.15 */ public Set locateAll(String relativePath, String codeNameBase, boolean localized) { File f = locate(relativePath, codeNameBase, localized); return f != null ? Collections.singleton(f) : Collections.emptySet(); } /** * Get a master locator. * Lookup is searched for all registered locators. * They are merged together and called in sequence * until one of them is able to service a request. * If you use this call, require the token org.openide.modules.InstalledFileLocator * to require any autoload modules which can provide locators. * @return a master merging locator (never null) */ public static InstalledFileLocator getDefault() { return DEFAULT; } private static InstalledFileLocator[] getInstances() { synchronized (LOCK) { if (instances != null) { return instances; } } Lookup.Result _result; synchronized (LOCK) { _result = result; } if (_result == null) { _result = Lookup.getDefault().lookupResult(InstalledFileLocator.class); _result.addLookupListener(new LookupListener() { public @Override void resultChanged(LookupEvent e) { synchronized (LOCK) { instances = null; } } }); synchronized (LOCK) { result = _result; } } Collection c = _result.allInstances(); synchronized (LOCK) { return instances = c.toArray(new InstalledFileLocator[c.size()]); } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy