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

org.flowable.osgi.BarTransformer Maven / Gradle / Ivy

There is a newer version: 7.0.1
Show newest version
/* Licensed 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.flowable.osgi;

import static org.flowable.osgi.Constants.BUNDLE_FLOWABLE_HEADER;
import static org.osgi.framework.Constants.BUNDLE_MANIFESTVERSION;
import static org.osgi.framework.Constants.BUNDLE_SYMBOLICNAME;
import static org.osgi.framework.Constants.BUNDLE_VERSION;

import java.io.OutputStream;
import java.net.URL;
import java.util.Set;
import java.util.TreeSet;
import java.util.jar.JarFile;
import java.util.jar.JarInputStream;
import java.util.jar.JarOutputStream;
import java.util.jar.Manifest;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.Deflater;
import java.util.zip.ZipEntry;

/**
 * @author Guillaume Nodet
 */
public class BarTransformer {

    public static void transform(URL url, OutputStream os) throws Exception {
        // Heuristicly retrieve name and version
        String name = url.getPath();
        int idx = name.lastIndexOf('/');
        if (idx >= 0) {
            name = name.substring(idx + 1);
        }
        String[] str = extractNameVersionType(name);
        // Build the list of folders containing resources
        String pathHeader;
        JarInputStream jis = new JarInputStream(url.openStream());
        try {
            Set paths = new TreeSet<>();
            ZipEntry e;
            while ((e = jis.getNextEntry()) != null) {
                String n = e.getName();
                int i = n.lastIndexOf('/');
                if (-1 == i) {// Add root path if the .bpmn20.xml is in the root
                    // of the bar file and the value is
                    // example.bpmn20.xml
                    paths.add("/"); // Extender#checkBundle calls the
                    // HeaderParser#parseHeader and it does not
                    // parse an empty string
                } else if (i < n.length() - 1) {
                    paths.add(n.substring(0, i + 1));
                }
            }
            StringBuilder sb = new StringBuilder();
            for (String s : paths) {
                if (sb.length() > 0) {
                    sb.append(",");
                }
                sb.append(s);
            }
            pathHeader = sb.toString();
        } finally {
            jis.close();
        }
        // Build the stream
        jis = new JarInputStream(url.openStream());
        try {
            JarOutputStream jos = new JarOutputStream(os);
            jos.setLevel(Deflater.NO_COMPRESSION);
            // Transform manifest
            Manifest m = jis.getManifest();
            if (m == null) {
                m = new Manifest();
                m.getMainAttributes().putValue("Manifest-Version", "2");
            }
            if (m.getMainAttributes().getValue(BUNDLE_MANIFESTVERSION) == null) {
                m.getMainAttributes().putValue(BUNDLE_MANIFESTVERSION, "2");
            }
            if (m.getMainAttributes().getValue(BUNDLE_SYMBOLICNAME) == null) {
                m.getMainAttributes().putValue(BUNDLE_SYMBOLICNAME, str[0]);
            }
            if (m.getMainAttributes().getValue(BUNDLE_VERSION) == null) {
                m.getMainAttributes().putValue(BUNDLE_VERSION, str[1]);
            }
            m.getMainAttributes().putValue(BUNDLE_FLOWABLE_HEADER, pathHeader);
            // Write manifest
            ZipEntry e = new ZipEntry(JarFile.MANIFEST_NAME);
            jos.putNextEntry(e);
            m.write(jos);
            jos.closeEntry();
            // Write all entries
            byte[] readBuffer = new byte[8192];
            while ((e = jis.getNextEntry()) != null) {
                ZipEntry e2 = new ZipEntry(e.getName());
                // e2.setMethod(ZipEntry.STORED);
                // e2.setSize(e.getSize());
                // e2.setCrc(e.getCrc());
                jos.putNextEntry(e2);
                int bytesIn = jis.read(readBuffer);
                while (bytesIn != -1) {
                    jos.write(readBuffer, 0, bytesIn);
                    bytesIn = jis.read(readBuffer);
                }
                jos.closeEntry();
            }
            jos.finish();
            jos.flush();
        } finally {
            jis.close();
        }
    }

    private static final String DEFAULT_VERSION = "0.0.0";

    private static final Pattern ARTIFACT_MATCHER = Pattern.compile("(.+)(?:-(\\d+)(?:\\.(\\d+)(?:\\.(\\d+))?)?(?:[^a-zA-Z0-9](.*))?)(?:\\.([^\\.]+))", Pattern.DOTALL);
    private static final Pattern FUZZY_MODIFIDER = Pattern.compile("(?:\\d+[.-])*(.*)", Pattern.DOTALL);

    public static String[] extractNameVersionType(String url) {
        Matcher m = ARTIFACT_MATCHER.matcher(url);
        if (!m.matches()) {
            return new String[]{url, DEFAULT_VERSION};
        } else {
            // System.err.println(m.groupCount());
            // for (int i = 1; i <= m.groupCount(); i++) {
            // System.err.println("Group " + i + ": " + m.group(i));
            // }

            StringBuffer v = new StringBuffer();
            String d1 = m.group(1);
            String d2 = m.group(2);
            String d3 = m.group(3);
            String d4 = m.group(4);
            String d5 = m.group(5);
            String d6 = m.group(6);
            if (d2 != null) {
                v.append(d2);
                if (d3 != null) {
                    v.append('.');
                    v.append(d3);
                    if (d4 != null) {
                        v.append('.');
                        v.append(d4);
                        if (d5 != null) {
                            v.append(".");
                            cleanupModifier(v, d5);
                        }
                    } else if (d5 != null) {
                        v.append(".0.");
                        cleanupModifier(v, d5);
                    }
                } else if (d5 != null) {
                    v.append(".0.0.");
                    cleanupModifier(v, d5);
                }
            }
            return new String[]{d1, v.toString(), d6};
        }
    }

    private static void cleanupModifier(StringBuffer result, String modifier) {
        Matcher m = FUZZY_MODIFIDER.matcher(modifier);
        if (m.matches()) {
            modifier = m.group(1);
        }
        for (int i = 0; i < modifier.length(); i++) {
            char c = modifier.charAt(i);
            if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_' || c == '-') {
                result.append(c);
            }
        }
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy