Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/Java/Netbeans/nbbuild/antsrc/org/netbeans/nbbuild/   (Apache JAVA IDE Version 28©)  Datei vom 3.10.2025 mit Größe 39 kB image not shown  

Quelle  MakeOSGi.java   Sprache: JAVA

 
/*
 * 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.netbeans.nbbuild;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URI;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.jar.Attributes;
import java.util.jar.JarFile;
import java.util.jar.JarOutputStream;
import java.util.jar.Manifest;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.CRC32;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.taskdefs.Copy;
import org.apache.tools.ant.types.ResourceCollection;
import org.apache.tools.ant.types.resources.FileResource;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;

/**
 * Converts a set of NetBeans modules into OSGi bundles.
 * Since there are some aspects of the translation that must be sensitive to
 * context in order to preserve as closely as possible the semantics of the
 * NetBeans module system, processing proceeds in two phases:
 * <ol>
 * <li>Each module in the input is opened and scanned for packages which it defines
 *     (including in its {@code Class-Path} extensions), and for packages which it
 *     (statically) refers to (not including packages it itself defines, or any
 *     packages in the {@code java.*} namespace). {@code OpenIDE-Module-Hide-Classpath-Packages}
 *     declarations are also tracked, and a list of packages which seem to be
 *     exported from this module (if any) is collected.
 * <li>Each module in the input is reopened. Now it is actually converted to an
 *     OSGi bundle. Package import and export information from the first phase is
 *     used to decide how to represent this bundle's imports:
 *     <ol>
 *     <li>Packages hidden by this bundle, or one of its direct dependencies, are
 *         never to be represented in the OSGi manifest.
 *     <li>Packages exported by one of this bundle's dependencies can also be skipped,
 *         since {@code Require-Bundle} will pick them all up.
 *     <li>Packages in the {@code org.osgi.*} namespace can be imported.
 *     <li>Packages from the known Java Platform API can be imported.
 *     <li>All other packages can be dynamically imported. Perhaps these will be
 *         available somehow at runtime, perhaps from the system bundle.
 *     </ol>
 * </ol>
 */

public class MakeOSGi extends Task {

    private File destdir;
    private List<ResourceCollection> modules = new ArrayList<>();
    
    /**
     * Mandatory destination directory. Bundles will be created here.
     */

    public void setDestdir(File destdir) {
        this.destdir = destdir;
    }
    
    /**
     * Adds a set of module JARs.
     * It is permitted for them to be JARs anywhere on disk,
     * but it is best if they are in a cluster structure
     * with ../update_tracking/*.xml present
     * so that associated files can be included in the bundle.
     */

    public void add(ResourceCollection modules) {
        this.modules.add(modules);
    }

    static class Info {
        final Set<String> importedPackages = new TreeSet<>();
        final Set<String> exportedPackages = new TreeSet<>();
        final Set<String> hiddenPackages = new TreeSet<>();
        final Set<String> hiddenSubpackages = new TreeSet<>();
    }

    public @Override void execute() throws BuildException {
        if (destdir == null) {
            throw new BuildException("missing destdir");
        }
        List<File> jars = new ArrayList<>();
        List<File> fragments = new ArrayList<>();
        Map<String,Info> infos = new HashMap<>();
        log("Prescanning JARs...");
        for (ResourceCollection rc : modules) {
            Iterator<?> it = rc.iterator();
            while (it.hasNext()) {
                File jar = ((FileResource) it.next()).getFile();
                log("Prescanning " + jar, Project.MSG_VERBOSE);
                if (jar.getParentFile().getName().equals("locale")) {
                    fragments.add(jar);
                    continue;
                }
                try {
                    try (JarFile jf = new JarFile(jar)) {
                        Info info = new Info();
                        String cnb = prescan(jf, info, this);
                        if (cnb == null) {
                            log(jar + " does not appear to be either a module or a bundle; skipping", Project.MSG_WARN);
                        } else if (SKIPPED_PSEUDO_MODULES.contains(cnb)) {
                            log("Skipping " + jar);
                        } else if (infos.containsKey(cnb)) {
                            log(jar + " appears to not be the only module named " + cnb, Project.MSG_WARN);
                        } else {
                            infos.put(cnb, info);
                            jars.add(jar);
                        }
                    }
                } catch (Exception x) {
                    throw new BuildException("Could not prescan " + jar + ": " + x, x, getLocation());
                }
            }
        }
        for (File jar : jars) {
            try {
                process(jar, infos);
            } catch (Exception x) {
                throw new BuildException("Could not process " + jar + ": " + x, x, getLocation());
            }
        }
        for (File jar : fragments) {
            try {
                processFragment(jar);
            } catch (Exception x) {
                throw new BuildException("Could not process " + jar + ": " + x, x, getLocation());
            }
        }
    }

    static String prescan(JarFile module, Info info, Task task) throws Exception {
        Manifest manifest = module.getManifest();
        if (manifest == null) {
            return null;
        }
        Attributes attr = manifest.getMainAttributes();
        String cnb = attr.getValue("OpenIDE-Module");
        if ("org.netbeans.libs.osgi".equals(cnb)) {
            // Otherwise get e.g. CCE: org.netbeans.core.osgi.Activator cannot be cast to org.osgi.framework.BundleActivator
            return cnb;
        }
        Set<String> availablePackages = new TreeSet<>();
        scanClasses(module, info.importedPackages, availablePackages, task);
        File antlib = new File(module.getName().replaceFirst("([/\\\\])modules([/\\\\][^/\\\\]+)""$1ant$1nblib$2"));
        if (antlib.isFile()) {
            // ant/nblib/org-netbeans-modules-debugger-jpda-ant.jar references com.sun.jdi.* packages.
            // AntBridge.MainClassLoader.findClass will refuse to load these,
            // since it is expected that the module loader, thus also AuxClassLoader, can load them.
            // So we need to DynamicImport-Package these packages so that will be true.
            Set<String> antlibPackages = new HashSet<>();
            try (JarFile antlibJF = new JarFile(antlib)) {
                scanClasses(antlibJF, antlibPackages, new HashSet<>(), task);
            }
            for (String antlibImport : antlibPackages) {
                if (!antlibImport.startsWith("org.apache.tools.") && !availablePackages.contains(antlibImport)) {
                    info.importedPackages.add(antlibImport);
                }
            }
        }
        if (cnb != null) {
            cnb = cnb.replaceFirst("/\\d+$""");
            String hide = attr.getValue("OpenIDE-Module-Hide-Classpath-Packages");
            if (hide != null) {
                for (String piece : hide.split("[, ]+")) {
                    if (piece.isEmpty()) {
                        continue;
                    }
                    if (piece.endsWith(".*")) {
                        info.hiddenPackages.add(piece.substring(0, piece.length() - ".*".length()));
                    } else if (piece.endsWith(".**")) {
                        info.hiddenSubpackages.add(piece.substring(0, piece.length() - ".**".length()));
                    } else {
                        throw new IOException("Bad OpenIDE-Module-Hide-Classpath-Packages piece: " + piece);
                    }
                }
            }
            String pp = attr.getValue("OpenIDE-Module-Public-Packages");
            String implVersion = attr.getValue("OpenIDE-Module-Implementation-Version");
            if (implVersion != null && implVersion.matches("\\d+") &&
                    /* not just e.g. 201005242201 */ attr.getValue("OpenIDE-Module-Build-Version") != null) {
                // Since we have no idea who might be using these packages, have to make everything public.
                info.exportedPackages.addAll(availablePackages);
                pp = null;
            }
            if (pp != null && !pp.equals("-")) {
                for (String p : pp.split("[, ]+")) {
                    if (p.isEmpty()) {
                        continue;
                    }
                    if (p.endsWith(".*")) {
                        info.exportedPackages.add(p.substring(0, p.length() - ".*".length()));
                    } else {
                        if (!p.endsWith(".**")) {
                            throw new IllegalArgumentException("Invalid package export: " + p);
                        }
                        for (String actual : availablePackages) {
                            if (actual.equals(p.substring(0, p.length() - ".**".length()))
                                    || actual.startsWith(p.substring(0, p.length() - "**".length()))) {
                                info.exportedPackages.add(actual);
                            }
                        }
                    }
                }
            }
        } else { // #180201
            cnb = JarWithModuleAttributes.extractCodeName(attr);
            if (cnb == null) {
                return null;
            }
            String exportPackage = attr.getValue("Export-Package");
            if (exportPackage != null) {
                // http://stackoverflow.com/questions/1757065/java-splitting-a-comma-separated-string-but-ignoring-commas-in-quotes
                for (String piece : exportPackage.split(",(?=([^\"]*\"[^\"]*\")*[^\"]*$)")) {
                    info.exportedPackages.add(piece.trim().replaceFirst(";.+"""));
                }
            }
        }
        return cnb;
    }

    private File findDestFile(String bundleName, String bundleVersion) throws IOException {
        File destFile = new File(destdir, bundleName + (bundleVersion != null ? "-" + bundleVersion : "") + ".jar");
        for (File stale : destdir.listFiles()) {
            if (stale.getName().matches("\\Q" + bundleName + "\\E(-.+)?[.]jar") && !stale.equals(destFile)) {
                log("Deleting copy under old name: " + stale);
                if (!stale.delete()) {
                    throw new IOException("Could not delete: " + stale);
                }
            }
        }
        return destFile;
    }

    private void process(File module, Map<String,Info> infos) throws Exception {
        try (JarFile jar = new JarFile(module)) {
            Manifest netbeans = jar.getManifest();
            Attributes netbeansAttr = netbeans.getMainAttributes();
            if (netbeansAttr.getValue("Bundle-SymbolicName") != null) { // #180201
                File bundleFile = findDestFile(JarWithModuleAttributes.extractCodeName(netbeansAttr), netbeansAttr.getValue("Bundle-Version"));
                if (bundleFile.lastModified() > module.lastModified()) {
                    log("Skipping " + module + " since " + bundleFile + " is newer", Project.MSG_VERBOSE);
                    return;
                }
                Copy copy = new Copy();
                copy.setProject(getProject());
                copy.setOwningTarget(getOwningTarget());
                copy.setFile(module);
                copy.setTofile(bundleFile);
                copy.setVerbose(true);
                copy.execute();
                return;
            }
            Manifest osgi = new Manifest();
            Attributes osgiAttr = osgi.getMainAttributes();
            translate(netbeansAttr, osgiAttr, infos);
            String cnb = osgiAttr.getValue("Bundle-SymbolicName").replaceFirst(";.+""");
            File bundleFile = findDestFile(cnb, osgiAttr.getValue("Bundle-Version"));
            if (bundleFile.lastModified() > module.lastModified()) {
                log("Skipping " + module + " since " + bundleFile + " is newer", Project.MSG_VERBOSE);
                return;
            }
            log("Processing " + module + " into " + bundleFile);
            String dynamicImports = osgiAttr.getValue("DynamicImport-Package");
            if (dynamicImports != null) {
                log(cnb + " has imports of no known origin: " + dynamicImports, Project.MSG_WARN);
                log("(you may need to define org.osgi.framework.system.packages.extra in your OSGi container)");
            }
            Properties localizedStrings = new Properties();
            String locbundle = netbeansAttr.getValue("OpenIDE-Module-Localizing-Bundle");
            if (locbundle != null) {
                try (InputStream is = jar.getInputStream(jar.getEntry(locbundle))) {
                    localizedStrings.load(is);
                }
                osgiAttr.putValue("Bundle-Localization", locbundle.replaceFirst("[.]properties$"""));
            }
            handleDisplayAttribute(localizedStrings, netbeansAttr, osgiAttr,
                    "OpenIDE-Module-Name""Bundle-Name");
            handleDisplayAttribute(localizedStrings, netbeansAttr, osgiAttr,
                    "OpenIDE-Module-Display-Category""Bundle-Category");
            handleDisplayAttribute(localizedStrings, netbeansAttr, osgiAttr,
                    "OpenIDE-Module-Short-Description""Bundle-Description");
            Map<String,File> bundledFiles = findBundledFiles(module, cnb);
            // XXX any use for OpenIDE-Module-Long-Description?
            String classPath = netbeansAttr.getValue("Class-Path");
            if (classPath != null) {
                StringBuilder bundleCP = new StringBuilder();
                for (String rawEntry : classPath.split("[, ]+")) {
                    String entry = URLDecoder.decode(rawEntry, "UTF-8");
                    if (entry.startsWith("${java.home}")) {
                        continue;
                    }
                    String clusterPath = new URI(module.getParentFile().getName() + "/" + entry).normalize().toString();
                    if (bundledFiles.containsKey(clusterPath)) {
                        bundleCP.append("/OSGI-INF/files/").append(clusterPath).append(",");
                    } else {
                        log("Class-Path entry " + entry + " from " + module + " does not correspond to any apparent cluster file", Project.MSG_WARN);
                    }
                }
                osgiAttr.putValue("Bundle-Classpath", bundleCP + ".");
            }
            StringBuilder execFiles = null;
            for (Map.Entry<String,File> bundledFile : bundledFiles.entrySet()) {
                // XXX would be better to use ${nbm.executable.files} as specified by project
                // (since building bundles on Windows will never set this even if running on Unix)
                // but this information is available only during the project's build or in its NBM
                if (bundledFile.getValue().canExecute()) {
                    String name = bundledFile.getKey();
                    if (execFiles == null) {
                        execFiles = new StringBuilder(name);
                    } else {
                        execFiles.append(',').append(name);
                    }
                }
            }
            if (execFiles != null) {
                osgiAttr.putValue("NetBeans-Executable-Files", execFiles.toString());
            }
            // XXX modules/lib/*.dll/so => Bundle-NativeCode (but syntax is rather complex)
            try (OutputStream bundle = new FileOutputStream(bundleFile);
                    ZipOutputStream zos = new JarOutputStream(bundle, osgi)) {
                Set<String> parents = new HashSet<>();
                Enumeration<? extends ZipEntry> entries = jar.entries();
                while (entries.hasMoreElements()) {
                    ZipEntry entry = entries.nextElement();
                    String path = entry.getName();
                    if (path.endsWith("/") || path.equals("META-INF/MANIFEST.MF")) {
                        continue;
                    }
                    try (InputStream is = jar.getInputStream(entry)) {
                        writeEntry(zos, path, is, parents);
                    }
                }
                for (Map.Entry<String,File> bundledFile : bundledFiles.entrySet()) {
                    try (InputStream is = new FileInputStream(bundledFile.getValue())) {
                        writeEntry(zos, "OSGI-INF/files/" + bundledFile.getKey(), is, parents);
                    }
                }
                zos.finish();
            }
        }
    }

    /**
     * Translate NetBeans module metadata to OSGi equivalents.
     * @param netbeans manifest header to be read
     * @param osgi manifest header to be written
     * @param infos information about imported and exported packages among all processed JARs
     */

    void translate(Attributes netbeans, Attributes osgi, Map<String,Info> infos) throws Exception {
        osgi.putValue("Manifest-Version""1.0"); // workaround for JDK bug
        osgi.putValue("Bundle-ManifestVersion""2");
        String codename = netbeans.getValue("OpenIDE-Module");
        if (codename == null) {
            throw new IllegalArgumentException("Does not appear to be a NetBeans module");
        }
        String cnb = codename.replaceFirst("/\\d+$""");
        osgi.putValue("Bundle-SymbolicName", cnb);
        if (cnb.equals("org.netbeans.core.osgi")) {
            osgi.putValue("Bundle-Activator""org.netbeans.core.osgi.Activator");
        }
        Info myInfo = infos.get(cnb);
        String spec = netbeans.getValue("OpenIDE-Module-Specification-Version");
        String bundleVersion = null;
        if (spec != null) {
            bundleVersion = threeDotsWithMajor(spec, codename);
            String buildVersion = netbeans.getValue("OpenIDE-Module-Build-Version");
            if (buildVersion == null) {
                buildVersion = netbeans.getValue("OpenIDE-Module-Implementation-Version");
            }
            if (buildVersion != null) {
                bundleVersion += "." + buildVersion.replaceAll("[^a-zA-Z0-9_-]""_");
            }
            osgi.putValue("Bundle-Version", bundleVersion);
        }
        // OpenIDE-Module-Friends is ignored since OSGi has no apparent equivalent
        // (could use mandatory export constraints but friends would then
        // need to use Import-Package to access, rather than Require-Bundle,
        // which would require knowing which packages are being imported by that dep)
        if (!myInfo.exportedPackages.isEmpty()) {
            StringBuilder b = new StringBuilder();
            for (String p : myInfo.exportedPackages) {
                if (b.length() > 0) {
                    b.append(", ");
                }
                b.append(p);
            }
            osgi.putValue("Export-Package", b.toString());
        }
        for (String attrToCopy : new String[] {"OpenIDE-Module-Layer""OpenIDE-Module-Install"}) {
            String val = netbeans.getValue(attrToCopy);
            if (val != null) {
                osgi.putValue(attrToCopy, val);
            }
        }
        StringBuilder requireBundles = new StringBuilder();
        if (!STARTUP_PSEUDO_MODULES.contains(cnb)) {
            // do not need to import any API, just need it to be started:
            requireBundles.append("org.netbeans.core.osgi");
        }
        Set<String> imports = new TreeSet<>(myInfo.importedPackages);
        hideImports(imports, myInfo);
        String dependencies = netbeans.getValue("OpenIDE-Module-Module-Dependencies");
        if (dependencies != null) {
            for (String dependency : dependencies.split(" *, *")) {
                String depCnb = translateDependency(requireBundles, dependency);
                if (depCnb == null) {
                    continue;
                }
                Info imported = infos.get(depCnb);
                if (imported != null) {
                    imports.removeAll(imported.exportedPackages);
                    hideImports(imports, imported);
                } else {
                    log("dependency " + depCnb + " of " + cnb + " not found in batch; imports may not be correct", Project.MSG_WARN);
                }
            }
        }
        if (requireBundles.length() > 0) {
            osgi.putValue("Require-Bundle", requireBundles.toString());
        }
        StringBuilder staticImports = new StringBuilder();
        StringBuilder dynamicImports = new StringBuilder();
        for (String pkg : imports) {
            StringBuilder b = isOSGiOrJavaPlatform(pkg) ? staticImports : dynamicImports;
            // JRE-specific dependencies will not be exported by Felix by default.
            // But Felix can be configured to offer any desired packages from the framework.
            // Do not use DynamicImport-Package where not really needed, as it can lead to deadlocks in Felix:
            // ModuleImpl.findClassOrResourceByDelegation -> Felix.acquireGlobalLock
            if (b.length() > 0) {
                b.append(", ");
            }
            b.append(pkg);
        }
        if (staticImports.length() > 0) {
            osgi.putValue("Import-Package", staticImports.toString());
        }
        if (dynamicImports.length() > 0) {
            osgi.putValue("DynamicImport-Package", dynamicImports.toString());
        }
        // ignore OpenIDE-Module-Package-Dependencies; rarely used, and bytecode analysis is probably more accurate anyway
        String javaDeps = netbeans.getValue("OpenIDE-Module-Java-Dependencies");
        if (javaDeps != null) {
            Matcher m = Pattern.compile("Java > (1.[6-9])").matcher(javaDeps); // 1.5 is not supported anyway
            if (m.matches()) {
                osgi.putValue("Bundle-RequiredExecutionEnvironment""JavaSE-" + m.group(1));
            }
        }
        for (String tokenAttr : new String[] {"OpenIDE-Module-Provides""OpenIDE-Module-Needs"}) {
            String v = netbeans.getValue(tokenAttr);
            if (v != null) {
                osgi.putValue(tokenAttr, v);
            }
        }
        String v = netbeans.getValue("OpenIDE-Module-Requires");
        if (v != null) {
            StringBuilder b = null;
            for (String tok : v.split("[, ]+")) {
                if (!tok.matches("org.openide.modules.ModuleFormat\\d+")) {
                    if (b == null) {
                        b = new StringBuilder(tok);
                    } else {
                        b.append(", ").append(tok);
                    }
                }
            }
            if (b != null) {
                osgi.putValue("OpenIDE-Module-Requires", b.toString());
            }
        }
        // autoload, eager status are ignored since OSGi has no apparent equivalent
    }

    private boolean isOSGiOrJavaPlatform(String pkg) {
        if (pkg.startsWith("org.osgi.")) {
            return true;
        }
        return JAVA_PLATFORM_PACKAGES.contains(pkg);
    }

    private static void hideImports(Set<String> imports, Info info) {
        imports.removeAll(info.hiddenPackages);
        Iterator<String> it = imports.iterator();
        while (it.hasNext()) {
            String p = it.next();
            for (String prefix : info.hiddenSubpackages) {
                if (p.equals(prefix) || p.startsWith(prefix + ".")) {
                    it.remove();
                    break;
                }
            }
        }
    }

    private static void writeEntry(ZipOutputStream zos, String path, InputStream data, Set<String> parents) throws IOException {
        int size = Math.max(data.available(), 100);
        ByteArrayOutputStream baos = new ByteArrayOutputStream(size);
        byte[] buf = new byte[size];
        int read;
        while ((read = data.read(buf)) != -1) {
            baos.write(buf, 0, read);
        }
        writeEntry(zos, path, baos.toByteArray(), parents);
    }
    private static void writeEntry(ZipOutputStream zos, String path, byte[] data, Set<String> parents) throws IOException {
        assert path.length() > 0 && !path.endsWith("/") && !path.startsWith("/") && path.indexOf("//") == -1 : path;
        for (int i = 0; i < path.length(); i++) {
            if (path.charAt(i) == '/') {
                String parent = path.substring(0, i + 1);
                if (parents.add(parent)) {
                    ZipEntry ze = new ZipEntry(parent);
                    ze.setMethod(ZipEntry.STORED);
                    ze.setSize(0);
                    ze.setCrc(0);
                    zos.putNextEntry(ze);
                    zos.closeEntry();
                }
            }
        }
        ZipEntry ze = new ZipEntry(path);
        ze.setMethod(ZipEntry.STORED);
        ze.setSize(data.length);
        CRC32 crc = new CRC32();
        crc.update(data);
        ze.setCrc(crc.getValue());
        zos.putNextEntry(ze);
        zos.write(data, 0, data.length);
        zos.closeEntry();
    }

    // copied from NetigsoModuleFactory
    private static String threeDotsWithMajor(String version, String withMajor) {
        int indx = withMajor.indexOf('/');
        int major = 0;
        if (indx > 0) {
            major = Integer.parseInt(withMajor.substring(indx + 1));
        }
        String[] segments = (version + ".0.0.0").split("\\.");
        assert segments.length >= 3 && segments[0].length() > 0;
        return (Integer.parseInt(segments[0]) + major * 100) + "."  + segments[1] + "." + segments[2];
    }

    static String translateDependency(StringBuilder b, String dependency) throws IllegalArgumentException {
        Matcher m = Pattern.compile("([^/ >=]+)(?:/(\\d+)(?:-(\\d+))?)? *(?:(=|>) *(.+))?").matcher(dependency);
        if (!m.matches()) {
            throw new IllegalArgumentException("bad dep: " + dependency);
        }
        String depCnb = m.group(1);
        if (SKIPPED_PSEUDO_MODULES.contains(depCnb)) {
            return null;
        }
        String depMajLo = m.group(2);
        String depMajHi = m.group(3);
        String comparison = m.group(4);
        String version = m.group(5);
        if (b.length() > 0) {
            b.append(", ");
        }
        b.append(depCnb);
        if (!"=".equals(comparison)) {
            if (version == null) {
                version = "0";
            }
            String targetVersion = threeDotsWithMajor(version, depMajLo == null ? "" : "x/" + depMajLo);
            b.append(";bundle-version=\"[").append(targetVersion).append(",");
            b.append(100 * ((depMajHi != null ? Integer.parseInt(depMajHi) : depMajLo != null ? Integer.parseInt(depMajLo) : 0) + 1));
            b.append(")\"");
        }
        return depCnb;
    }

    private void handleDisplayAttribute(Properties props, Attributes netbeans, Attributes osgi, String netbeansHeader, String osgiHeader) throws IOException {
        String val = netbeans.getValue(netbeansHeader);
        if (val != null) {
            osgi.putValue(osgiHeader, val);
        } else if (props.containsKey(netbeansHeader)) {
            osgi.putValue(osgiHeader, "%" + netbeansHeader);
        }
    }

    private Map<String,File> findBundledFiles(File module, String cnb) throws Exception {
        Map<String,File> result = new HashMap<>();
        if (module.getParentFile().getName().matches("modules|core|lib")) {
            File cluster = module.getParentFile().getParentFile();
            File updateTracking = new File(new File(cluster, "update_tracking"), cnb.replace('.''-') + ".xml");
            if (updateTracking.isFile()) {
                Document doc = XMLUtil.parse(new InputSource(updateTracking.toURI().toString()), falsefalsenullnull);
                NodeList nl = doc.getElementsByTagName("file");
                for (int i = 0; i < nl.getLength(); i++) {
                    String path = ((Element) nl.item(i)).getAttribute("name");
                    if (path.matches("config/(Modules|ModuleAutoDeps)/.+[.]xml|lib/nbexec.*")) {
                        continue;
                    }
                    File f = new File(cluster, path);
                    if (f.equals(module)) {
                        continue;
                    }
                    if (f.isFile()) {
                        result.put(path, f);
                    } else {
                        log("did not find " + f + " specified in " + updateTracking, Project.MSG_WARN);
                    }
                }
            } else {
                log("did not find expected " + updateTracking, Project.MSG_WARN);
            }
        } else {
            log("JAR " + module + " not found in expected cluster layout", Project.MSG_WARN);
        }
        return result;
    }

    private static void scanClasses(JarFile module, Set<String> importedPackages, Set<String> availablePackages, Task task) throws Exception {
        Map<String, byte[]> classfiles = new TreeMap<>();
        VerifyClassLinkage.read(module, classfiles, new HashSet<>(Collections.singleton(new File(module.getName()))), task, null);
        for (Map.Entry<String,byte[]> entry : classfiles.entrySet()) {
            String available = entry.getKey();
            int idx = available.lastIndexOf('.');
            if (idx != -1) {
                availablePackages.add(available.substring(0, idx));
            }
            for (String clazz : VerifyClassLinkage.dependencies(entry.getValue())) {
                if (classfiles.containsKey(clazz)) {
                    // Part of the same module; probably not an external import.
                    continue;
                }
                if (clazz.startsWith("java.")) {
                    // No need to declare as an import.
                    continue;
                }
                idx = clazz.lastIndexOf('.');
                if (idx != -1) {
                    importedPackages.add(clazz.substring(0, idx));
                }
            }
        }
    }

    private void processFragment(File fragment) throws Exception {
        String cnb = findFragmentHost(fragment);
        File bundleFile = new File(destdir, fragment.getName());
        if (bundleFile.lastModified() > fragment.lastModified()) {
            log("Skipping " + fragment + " since " + bundleFile + " is newer", Project.MSG_VERBOSE);
            return;
        }
        log("Processing " + fragment + " into " + bundleFile);
        Manifest mf = new Manifest();
        Attributes attr = mf.getMainAttributes();
        attr.putValue("Manifest-Version""1.0"); // workaround for JDK bug
        attr.putValue("Bundle-ManifestVersion""2");
        attr.putValue("Bundle-SymbolicName", cnb + "-branding");
        attr.putValue("Fragment-Host", cnb);
        try (JarFile jar = new JarFile(fragment);
                OutputStream bundle = new FileOutputStream(bundleFile);
                ZipOutputStream zos = new JarOutputStream(bundle, mf)) {
            Set<String> parents = new HashSet<>();
            Enumeration<? extends ZipEntry> entries = jar.entries();
            while (entries.hasMoreElements()) {
                ZipEntry entry = entries.nextElement();
                String path = entry.getName();
                if (path.endsWith("/") || path.equals("META-INF/MANIFEST.MF")) {
                    continue;
                }   try (InputStream is = jar.getInputStream(entry)) {
                    writeEntry(zos, path, is, parents);
                }
            }
            zos.finish();
        }
    }

    static String findFragmentHost(File jar) {
        String cnb = jar.getName().replaceFirst("(_[a-z][a-z0-9]*)*[.]jar$""").replace('-''.');
        // Historical naming patterns:
        if (cnb.equals("core") && jar.getParentFile().getParentFile().getName().equals("core")) {
            return "org.netbeans.core.startup";
        } else if (cnb.equals("boot") && jar.getParentFile().getParentFile().getName().equals("lib")) {
            return "org.netbeans.bootstrap";
        } else {
            return cnb;
        }
    }

    /**
     * List of packages guaranteed to be in the Java platform.
     * Taken from Felix's default.properties@1347814#jre-1.6 but same as JDK 6's package-list.
     * FELIX-2572 updated this to not include some packages actually in the JRE
     * (rt.jar and src.zip); can cause problems in some cases (cf. bug #210325 comment #11).
     */

    private static final Set<String> JAVA_PLATFORM_PACKAGES = new TreeSet<String>(Arrays.asList(
        "javax.accessibility",
        "javax.activation",
        "javax.activity",
        "javax.annotation",
        "javax.annotation.processing",
        "javax.crypto",
        "javax.crypto.interfaces",
        "javax.crypto.spec",
        "javax.imageio",
        "javax.imageio.event",
        "javax.imageio.metadata",
        "javax.imageio.plugins.bmp",
        "javax.imageio.plugins.jpeg",
        "javax.imageio.spi",
        "javax.imageio.stream",
        "javax.jws",
        "javax.jws.soap",
        "javax.lang.model",
        "javax.lang.model.element",
        "javax.lang.model.type",
        "javax.lang.model.util",
        "javax.management",
        "javax.management.loading",
        "javax.management.modelmbean",
        "javax.management.monitor",
        "javax.management.openmbean",
        "javax.management.relation",
        "javax.management.remote",
        "javax.management.remote.rmi",
        "javax.management.timer",
        "javax.naming",
        "javax.naming.directory",
        "javax.naming.event",
        "javax.naming.ldap",
        "javax.naming.spi",
        "javax.net",
        "javax.net.ssl",
        "javax.print",
        "javax.print.attribute",
        "javax.print.attribute.standard",
        "javax.print.event",
        "javax.rmi",
        "javax.rmi.CORBA",
        "javax.rmi.ssl",
        "javax.script",
        "javax.security.auth",
        "javax.security.auth.callback",
        "javax.security.auth.kerberos",
        "javax.security.auth.login",
        "javax.security.auth.spi",
        "javax.security.auth.x500",
        "javax.security.cert",
        "javax.security.sasl",
        "javax.sound.midi",
        "javax.sound.midi.spi",
        "javax.sound.sampled",
        "javax.sound.sampled.spi",
        "javax.sql",
        "javax.sql.rowset",
        "javax.sql.rowset.serial",
        "javax.sql.rowset.spi",
        "javax.swing",
        "javax.swing.border",
        "javax.swing.colorchooser",
        "javax.swing.event",
        "javax.swing.filechooser",
        "javax.swing.plaf",
        "javax.swing.plaf.basic",
        "javax.swing.plaf.metal",
        "javax.swing.plaf.multi",
        "javax.swing.plaf.synth",
        "javax.swing.table",
        "javax.swing.text",
        "javax.swing.text.html",
        "javax.swing.text.html.parser",
        "javax.swing.text.rtf",
        "javax.swing.tree",
        "javax.swing.undo",
        "javax.tools",
        "javax.transaction",
        "javax.transaction.xa",
        "javax.xml",
        "javax.xml.bind",
        "javax.xml.bind.annotation",
        "javax.xml.bind.annotation.adapters",
        "javax.xml.bind.attachment",
        "javax.xml.bind.helpers",
        "javax.xml.bind.util",
        "javax.xml.crypto",
        "javax.xml.crypto.dom",
        "javax.xml.crypto.dsig",
        "javax.xml.crypto.dsig.dom",
        "javax.xml.crypto.dsig.keyinfo",
        "javax.xml.crypto.dsig.spec",
        "javax.xml.datatype",
        "javax.xml.namespace",
        "javax.xml.parsers",
        "javax.xml.soap",
        "javax.xml.stream",
        "javax.xml.stream.events",
        "javax.xml.stream.util",
        "javax.xml.transform",
        "javax.xml.transform.dom",
        "javax.xml.transform.sax",
        "javax.xml.transform.stax",
        "javax.xml.transform.stream",
        "javax.xml.validation",
        "javax.xml.ws",
        "javax.xml.ws.handler",
        "javax.xml.ws.handler.soap",
        "javax.xml.ws.http",
        "javax.xml.ws.soap",
        "javax.xml.ws.spi",
        "javax.xml.ws.wsaddressing",
        "javax.xml.xpath",
        "org.ietf.jgss",
        "org.omg.CORBA",
        "org.omg.CORBA.DynAnyPackage",
        "org.omg.CORBA.ORBPackage",
        "org.omg.CORBA.TypeCodePackage",
        "org.omg.CORBA.portable",
        "org.omg.CORBA_2_3",
        "org.omg.CORBA_2_3.portable",
        "org.omg.CosNaming",
        "org.omg.CosNaming.NamingContextExtPackage",
        "org.omg.CosNaming.NamingContextPackage",
        "org.omg.Dynamic",
        "org.omg.DynamicAny",
        "org.omg.DynamicAny.DynAnyFactoryPackage",
        "org.omg.DynamicAny.DynAnyPackage",
        "org.omg.IOP",
        "org.omg.IOP.CodecFactoryPackage",
        "org.omg.IOP.CodecPackage",
        "org.omg.Messaging",
        "org.omg.PortableInterceptor",
        "org.omg.PortableInterceptor.ORBInitInfoPackage",
        "org.omg.PortableServer",
        "org.omg.PortableServer.CurrentPackage",
        "org.omg.PortableServer.POAManagerPackage",
        "org.omg.PortableServer.POAPackage",
        "org.omg.PortableServer.ServantLocatorPackage",
        "org.omg.PortableServer.portable",
        "org.omg.SendingContext",
        "org.omg.stub.java.rmi",
        "org.w3c.dom",
        "org.w3c.dom.bootstrap",
        "org.w3c.dom.events",
        "org.w3c.dom.ls",
        "org.xml.sax",
        "org.xml.sax.ext",
        "org.xml.sax.helpers"
    ));

    private static final Set<String> SKIPPED_PSEUDO_MODULES = new HashSet<String>(Arrays.asList(
            "org.eclipse.osgi",
            "org.netbeans.core.netigso",
            "org.netbeans.modules.netbinox",
            "org.netbeans.libs.osgi",
            "org.netbeans.libs.felix"
    ));

    private static final Set<String> STARTUP_PSEUDO_MODULES = new HashSet<String>(Arrays.asList(
            "org.openide.util.lookup",
            "org.openide.util.ui",
            "org.openide.util",
            "org.openide.modules",
            "org.netbeans.bootstrap",
            "org.openide.filesystems",
            "org.openide.filesystems.compat8",
            "org.netbeans.core.startup",
            "org.netbeans.core.startup.base",
            "org.netbeans.core.osgi",
            "org.eclipse.osgi"
    ));

}

Messung V0.5
C=95 H=88 G=91

¤ Dauer der Verarbeitung: 0.4 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.