    1   /*
    2    * Licensed to the Apache Software Foundation (ASF) under one
    3    * or more contributor license agreements.  See the NOTICE file
    4    * distributed with this work for additional information
    5    * regarding copyright ownership.  The ASF licenses this file
    6    * to you under the Apache License, Version 2.0 (the
    7    * "License"); you may not use this file except in compliance
    8    * with the License.  You may obtain a copy of the License at
    9    *
    10   *   http://www.apache.org/licenses/LICENSE-2.0
    11   *
    12   * Unless required by applicable law or agreed to in writing,
    13   * software distributed under the License is distributed on an
    14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    15   * KIND, either express or implied.  See the License for the
    16   * specific language governing permissions and limitations
    17   * under the License.
    18   */
    19  package org.apache.felix.bundleplugin;
    20
    21
    22  import java.io.BufferedReader;
    23  import java.io.ByteArrayInputStream;
    24  import java.io.ByteArrayOutputStream;
    25  import java.io.IOException;
    26  import java.io.InputStream;
    27  import java.io.InputStreamReader;
    28  import java.net.URL;
    29  import java.util.ArrayList;
    30  import java.util.Arrays;
    31  import java.util.HashSet;
    32  import java.util.LinkedHashMap;
    33  import java.util.List;
    34  import java.util.Map;
    35  import java.util.Set;
    36  import java.util.TreeSet;
    37  import java.util.regex.Pattern;
    38
    39  import javax.xml.transform.Transformer;
    40  import javax.xml.transform.TransformerFactory;
    41  import javax.xml.transform.stream.StreamResult;
    42  import javax.xml.transform.stream.StreamSource;
    43
    44  import aQute.bnd.osgi.Analyzer;
    45  import aQute.bnd.osgi.Descriptors.PackageRef;
    46  import aQute.bnd.osgi.Jar;
    47  import aQute.bnd.osgi.Processor;
    48  import aQute.bnd.osgi.Resource;
    49  import aQute.bnd.service.AnalyzerPlugin;
    50  import aQute.libg.generics.Create;
    51  import org.apache.felix.utils.manifest.Attribute;
    52  import org.apache.felix.utils.manifest.Clause;
    53  import org.osgi.framework.Constants;
    54
    55  import static org.apache.felix.utils.manifest.Parser.parseHeader;
    56
    57
    58  public class ScrPlugin implements AnalyzerPlugin
    59  {
    60
    61      Transformer transformer;
    62
    63      public ScrPlugin() throws Exception
    64      {
    65          transformer = getTransformer( getClass().getResource( "scr.xsl" ) );
    66      }
    67
    68
    69      public boolean analyzeJar( Analyzer analyzer ) throws Exception
    70      {
    71          Set<String> headers = Create.set();
    72
    73          String bpHeader = analyzer.getProperty( "Service-Component" );
    74
    75          Map<String, ? extends Map<String, String>> map = Processor.parseHeader( bpHeader, null );
    76          for ( String root : map.keySet() )
    77          {
    78              Resource resource = analyzer.getJar().getResource(root);
    79              if ( resource != null ) {
    80                  process(analyzer, root, resource, headers);
    81              }
    82          }
    83
    84          // Group and analyze
    85          for ( String str : headers )
    86          {
    87              int idx = str.indexOf( ':' );
    88              if ( idx < 0 )
    89              {
    90                  analyzer.warning( ( new StringBuilder( "Error analyzing services in scr resource: " ) ).append( str ).toString() );
    91                  continue;
    92              }
    93              String h = str.substring( 0, idx ).trim();
    94              String v = str.substring( idx + 1 ).trim();
    95
    96              StringBuilder sb = new StringBuilder();
    97              String header = analyzer.getProperty( h );
    98              if (header != null && !header.isEmpty())
    99              {
    100                 sb.append(header);
    101                 sb.append(",");
    102             }
    103             sb.append( v );
    104             analyzer.setProperty(h, sb.toString());
    105         }
    106         return false;
    107     }
    108
    109
    110     private void process( Analyzer analyzer, String path, Resource resource, Set<String> headers )
    111     {
    112         InputStream in = null;
    113         try
    114         {
    115             in = resource.openInputStream();
    116
    117             // Retrieve headers
    118             Set<String> set = analyze( in );
    119             headers.addAll( set );
    120         }
    121         catch ( Exception e )
    122         {
    123             analyzer.error( ( new StringBuilder( "Unexpected exception in processing scr resources(" ) )
    124                 .append( path ).append( "): " ).append( e ).toString() );
    125         }
    126         finally
    127         {
    128             try
    129             {
    130                 if ( in != null )
    131                 {
    132                     in.close();
    133                 }
    134             }
    135             catch ( IOException e )
    136             {
    137             }
    138         }
    139     }
    140
    141
    142     public Set<String> analyze( InputStream in ) throws Exception
    143     {
    144         Set<String> refers = new HashSet<String>();
    145         ByteArrayOutputStream bout = new ByteArrayOutputStream();
    146         javax.xml.transform.Result r = new StreamResult( bout );
    147         javax.xml.transform.Source s = new StreamSource( in );
    148         transformer.transform( s, r );
    149         ByteArrayInputStream bin = new ByteArrayInputStream( bout.toByteArray() );
    150         bout.close();
    151         BufferedReader br = new BufferedReader( new InputStreamReader( bin ) );
    152         for ( String line = br.readLine(); line != null; line = br.readLine() )
    153         {
    154             line = line.trim();
    155             if ( line.length() > 0 )
    156             {
    157                 refers.add( line );
    158             }
    159         }
    160
    161         br.close();
    162         return refers;
    163     }
    164
    165
    166     protected Transformer getTransformer( URL url ) throws Exception
    167     {
    168         TransformerFactory tf = TransformerFactory.newInstance();
    169         javax.xml.transform.Source source = new StreamSource( url.openStream() );
    170         return tf.newTransformer( source );
    171     }
    172
    173 }