Package org.apache.felix.sigil.common.obr.impl

Source Code of org.apache.felix.sigil.common.obr.impl.OBRHandler

/*
* 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.apache.felix.sigil.common.obr.impl;

import java.io.File;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;

import org.apache.felix.sigil.common.model.ModelElementFactory;
import org.apache.felix.sigil.common.model.eclipse.ISigilBundle;
import org.apache.felix.sigil.common.model.osgi.IBundleModelElement;
import org.apache.felix.sigil.common.model.osgi.IPackageExport;
import org.apache.felix.sigil.common.model.osgi.IPackageImport;
import org.apache.felix.sigil.common.model.osgi.IRequiredBundle;
import org.apache.felix.sigil.common.osgi.LDAPExpr;
import org.apache.felix.sigil.common.osgi.LDAPParseException;
import org.apache.felix.sigil.common.osgi.LDAPParser;
import org.apache.felix.sigil.common.osgi.SimpleTerm;
import org.apache.felix.sigil.common.osgi.VersionRange;
import org.apache.felix.sigil.common.osgi.VersionTable;
import org.xml.sax.Attributes;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.xml.sax.helpers.DefaultHandler;

final class OBRHandler extends DefaultHandler
{
    private static final String PACKAGE = "package";
    private static final String URI = "uri";
    private static final String PRESENTATION_NAME = "presentationname";
    private static final String VERSION = "version";
    private static final String SYMBOLIC_NAME = "symbolicname";
    private final File cacheDir;
    private final URL obrURL;
    private final OBRListener listener;

    private HashSet<String> sanity = new HashSet<String>();
    private Locator locator;
    private ISigilBundle bundle;
    private IPackageExport export;
    private int depth;

    public OBRHandler(URL obrURL, File bundleCache, OBRListener listener)
    {
        this.obrURL = obrURL;
        this.cacheDir = bundleCache;
        this.listener = listener;
    }

    public void setDocumentLocator(Locator locator)
    {
        this.locator = locator;
    }

    public void startElement(String uri, String localName, String qName,
        Attributes attributes) throws SAXException
    {
        if (depth++ == 0 && !"repository".equals(qName))
        {
            throw new SAXParseException(
                "Invalid OBR document, expected repository top level element", locator);
        }
        else if ("resource".equals(qName))
        {
            startResource(attributes);
        }
        else if ("capability".equals(qName))
        {
            startCapability(attributes);
        }
        else if ("require".equals(qName))
        {
            startRequire(attributes);
        }
        else if ("p".equals(qName))
        {
            startProperty(attributes);
        }
    }

    public void endElement(String uri, String localName, String qName)
        throws SAXException
    {
        depth--;
        if ("resource".equals(qName))
        {
            endResource();
        }
        else if ("capability".equals(qName))
        {
            endCapability();
        }
        else if ("require".equals(qName))
        {
            endRequire();
        }
        else if ("p".equals(qName))
        {
            endProperty();
        }
    }

    private void startResource(Attributes attributes) throws SAXException
    {
        try
        {
            String uri = attributes.getValue("", URI);
            if (uri.endsWith(".jar"))
            {
                if (!sanity.add(uri))
                {
                    // TODO replace with logging framework for build
                    // should hook in with ide/build logging
                    System.err.println(obrURL + " contains duplicate uri: " + uri);
                }
               
                ISigilBundle b = ModelElementFactory.getInstance().newModelElement(
                    ISigilBundle.class);
                IBundleModelElement info = ModelElementFactory.getInstance().newModelElement(
                    IBundleModelElement.class);
                info.setSymbolicName(attributes.getValue("", SYMBOLIC_NAME));
                info.setVersion(VersionTable.getVersion(attributes.getValue("", VERSION)));
                info.setName(attributes.getValue("", PRESENTATION_NAME));
                URI l = makeAbsolute(uri);
                info.setUpdateLocation(l);
                if ("file".equals(l.getScheme()))
                {
                    b.setLocation(new File(l));
                }
                else
                {
                    b.setLocation(cachePath(info));
                }
                b.setBundleInfo(info);
                bundle = b;
            }
        }
        catch (Exception e)
        {
            throw new SAXParseException("Failed to build bundle info", locator, e);
        }
    }

    private URI makeAbsolute(String uri) throws URISyntaxException
    {
        URI l = new URI(uri);
        if (!l.isAbsolute())
        {
            String base = obrURL.toExternalForm();
            int i = base.lastIndexOf("/");
            if (i != -1)
            {
                base = base.substring(0, i);
                l = new URI(base + (uri.startsWith("/") ? "" : "/") + uri);
            }
        }
        return l;
    }

    private File cachePath(IBundleModelElement info)
    {
        return new File(cacheDir, info.getSymbolicName() + "_" + info.getVersion()
            + ".jar");
    }

    private void startCapability(Attributes attributes)
    {
        if (bundle != null)
        {
            if (PACKAGE.equals(attributes.getValue("", "name")))
            {
                export = ModelElementFactory.getInstance().newModelElement(
                    IPackageExport.class);
            }
        }
    }

    private void startRequire(Attributes attributes) throws SAXParseException
    {
        if (bundle != null)
        {
            String name = attributes.getValue("name");
            if (PACKAGE.equals(name))
            {
                IPackageImport pi = ModelElementFactory.getInstance().newModelElement(
                    IPackageImport.class);
                try
                {
                    LDAPExpr expr = LDAPParser.parseExpression(attributes.getValue("filter"));
                    pi.setPackageName(decodePackage(expr, locator));
                    pi.setVersions(decodeVersions(expr, locator));
                    pi.setOptional(Boolean.valueOf(attributes.getValue("optional")));
                    bundle.getBundleInfo().addImport(pi);
                }
                catch (LDAPParseException e)
                {
                    throw new SAXParseException("Failed to parse filter", locator, e);
                }
            }
            else if ("bundle".equals(name))
            {
                IRequiredBundle b = ModelElementFactory.getInstance().newModelElement(
                    IRequiredBundle.class);
                try
                {
                    LDAPExpr expr = LDAPParser.parseExpression(attributes.getValue("filter"));
                    b.setSymbolicName(decodeSymbolicName(expr, locator));
                    b.setVersions(decodeVersions(expr, locator));
                    b.setOptional(Boolean.valueOf(attributes.getValue("optional")));
                    bundle.getBundleInfo().addRequiredBundle(b);
                }
                catch (Exception e)
                {
                    System.err.println("Failed to parse filter in bundle "
                        + bundle.getBundleInfo().getSymbolicName());
                    throw new SAXParseException("Failed to parse filter in bundle "
                        + bundle.getBundleInfo().getSymbolicName(), locator, e);
                }
            }
            //else if ( "ee".equals( name ) ) {
            // TODO ignore for now...
            //}
            //else if ( "service".equals( name ) ) {
            // TODO ignore for now...
            //}
            //else {
            //  for ( int i = 0; i < attributes.getLength(); i++ ) {
            //    System.out.println( "Found requirement " + attributes.getValue(i) );       
            //  }
            //}
        }
    }

    private static VersionRange decodeVersions(LDAPExpr expr, Locator locator)
        throws SAXParseException
    {
        try
        {
            return VersionRangeHelper.decodeVersions(expr);
        }
        catch (NumberFormatException e)
        {
            throw new SAXParseException(e.getMessage(), locator);
        }
    }

    private void startProperty(Attributes attributes)
    {
        if (export != null)
        {
            String name = attributes.getValue("", "n");
            String value = attributes.getValue("", "v");
            if (PACKAGE.equals(name))
            {
                export.setPackageName(value);
            }
            else if ("uses".equals(name))
            {
                String[] split = value.split(",");
                export.setUses(Arrays.asList(split));
            }
            else if ("version".equals(name))
            {
                export.setVersion(VersionTable.getVersion(value));
            }
        }
    }

    private void endResource()
    {
        if (bundle != null)
        {
            listener.handleBundle(bundle);
            bundle = null;
        }
    }

    private void endCapability()
    {
        if (bundle != null)
        {
            if (export != null)
            {
                bundle.getBundleInfo().addExport(export);
                export = null;
            }
        }
    }

    private void endRequire()
    {
        // TODO Auto-generated method stub

    }

    private void endProperty()
    {
        // TODO Auto-generated method stub

    }

    private static String decodePackage(LDAPExpr expr, Locator locator)
        throws SAXParseException
    {
        ArrayList<SimpleTerm> terms = new ArrayList<SimpleTerm>(1);

        findTerms("package", expr, terms);

        if (terms.isEmpty())
        {
            throw new SAXParseException("Missing name filter in " + expr, locator);
        }

        return terms.get(0).getRval();
    }

    private static String decodeSymbolicName(LDAPExpr expr, Locator locator)
        throws SAXParseException
    {
        ArrayList<SimpleTerm> terms = new ArrayList<SimpleTerm>(1);

        findTerms("symbolicname", expr, terms);

        if (terms.isEmpty())
        {
            throw new SAXParseException("Missing name filter in " + expr, locator);
        }

        return terms.get(0).getRval();
    }

    private static void findTerms(String string, LDAPExpr expr, List<SimpleTerm> terms)
        throws SAXParseException
    {
        if (expr instanceof SimpleTerm)
        {
            SimpleTerm term = (SimpleTerm) expr;
            if (term.getName().equals(string))
            {
                terms.add(term);
            }
        }
        else
        {
            for (LDAPExpr c : expr.getChildren())
            {
                findTerms(string, c, terms);
            }
        }
    }
}
TOP

Related Classes of org.apache.felix.sigil.common.obr.impl.OBRHandler

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.