Skip to main content
aboutsummaryrefslogtreecommitdiffstats
blob: 7ceca896c17189d53d6238d48cf06499d3597d57 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
//
//  ========================================================================
//  Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
//  ------------------------------------------------------------------------
//  All rights reserved. This program and the accompanying materials
//  are made available under the terms of the Eclipse Public License v1.0
//  and Apache License v2.0 which accompanies this distribution.
//
//      The Eclipse Public License is available at
//      http://www.eclipse.org/legal/epl-v10.html
//
//      The Apache License v2.0 is available at
//      http://www.opensource.org/licenses/apache2.0.php
//
//  You may elect to redistribute this code under either of these licenses.
//  ========================================================================
//

package org.eclipse.jetty.osgi.annotations;

import java.util.HashSet;
import java.util.Set;

import org.eclipse.jetty.annotations.AnnotationParser.Handler;
import org.eclipse.jetty.annotations.ClassNameResolver;
import org.eclipse.jetty.osgi.boot.OSGiWebInfConfiguration;
import org.eclipse.jetty.osgi.boot.OSGiWebappConstants;
import org.eclipse.jetty.osgi.boot.utils.internal.PackageAdminServiceTracker;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.webapp.WebAppContext;
import org.osgi.framework.Bundle;
import org.osgi.framework.Constants;

/**
 * Extend the AnnotationConfiguration to support OSGi:
 * Look for annotations inside WEB-INF/lib and also in the fragments and required bundles.
 * Discover them using a scanner adapted to OSGi instead of the jarscanner. 
 */
public class AnnotationConfiguration extends org.eclipse.jetty.annotations.AnnotationConfiguration
{
    private static final Logger LOG = Log.getLogger(org.eclipse.jetty.annotations.AnnotationConfiguration.class);
    
    public class BundleParserTask extends ParserTask
    {
        
        public BundleParserTask (AnnotationParser parser, Set<? extends Handler>handlers, Resource resource, ClassNameResolver resolver)
        {
            super(parser, handlers, resource, resolver);
        }

        public Void call() throws Exception
        {
            if (_parser != null)
            {
                org.eclipse.jetty.osgi.annotations.AnnotationParser osgiAnnotationParser = (org.eclipse.jetty.osgi.annotations.AnnotationParser)_parser;
                Bundle bundle = osgiAnnotationParser.getBundle(_resource);
                if (_stat != null)
                    _stat.start();
                osgiAnnotationParser.parse(_handlers, bundle,  _resolver); 
                if (_stat != null)
                    _stat.end();
            }
            return null;
        }
    }
    
    
    public AnnotationConfiguration()
    {
        System.err.println("Constructed osgi.AnnotationConfiguration");
    }
    /**
     * This parser scans the bundles using the OSGi APIs instead of assuming a jar.
     */
    @Override
    protected org.eclipse.jetty.annotations.AnnotationParser createAnnotationParser()
    {
        return new AnnotationParser();
    }
    
    /**
     * Here is the order in which jars and osgi artifacts are scanned for discoverable annotations.
     * <ol>
     * <li>The container jars are scanned.</li>
     * <li>The WEB-INF/classes are scanned</li>
     * <li>The osgi fragment to the web bundle are parsed.</li>
     * <li>The WEB-INF/lib are scanned</li>
     * <li>The required bundles are parsed</li>
     * </ol>
     */
    @Override
    public void parseWebInfLib (WebAppContext context, org.eclipse.jetty.annotations.AnnotationParser parser)
    throws Exception
    {
        AnnotationParser oparser = (AnnotationParser)parser;
        
        Bundle webbundle = (Bundle) context.getAttribute(OSGiWebappConstants.JETTY_OSGI_BUNDLE);
        Set<Bundle> fragAndRequiredBundles = (Set<Bundle>)context.getAttribute(OSGiWebInfConfiguration.FRAGMENT_AND_REQUIRED_BUNDLES);
        if (fragAndRequiredBundles != null)
        {
            //index and scan fragments
            for (Bundle bundle : fragAndRequiredBundles)
            {
                Resource bundleRes = oparser.indexBundle(bundle);
                if (!context.getMetaData().getWebInfJars().contains(bundleRes))
                {
                    context.getMetaData().addWebInfJar(bundleRes);
                }
                
                if (bundle.getHeaders().get(Constants.FRAGMENT_HOST) != null)
                {
                    //a fragment indeed:
                    parseFragmentBundle(context,oparser,webbundle,bundle);
                }
            }
        }
        //scan ourselves
        oparser.indexBundle(webbundle);
        parseWebBundle(context,oparser,webbundle);
        
        //scan the WEB-INF/lib
        super.parseWebInfLib(context,parser);
        if (fragAndRequiredBundles != null)
        {
            //scan the required bundles
            for (Bundle requiredBundle : fragAndRequiredBundles)
            {
                if (requiredBundle.getHeaders().get(Constants.FRAGMENT_HOST) == null)
                {
                    //a bundle indeed:
                    parseRequiredBundle(context,oparser,webbundle,requiredBundle);
                }
            }
        }
    }
    
    /**
     * Scan a fragment bundle for servlet annotations
     * @param context The webapp context
     * @param parser The parser
     * @param webbundle The current webbundle
     * @param fragmentBundle The OSGi fragment bundle to scan
     * @throws Exception
     */
    protected void parseFragmentBundle(WebAppContext context, AnnotationParser parser,
            Bundle webbundle, Bundle fragmentBundle) throws Exception
    {
        parseBundle(context,parser,webbundle,fragmentBundle);
    }
    
    /**
     * Scan a bundle required by the webbundle for servlet annotations
     * @param context The webapp context
     * @param parser The parser
     * @param webbundle The current webbundle
     * @param fragmentBundle The OSGi required bundle to scan
     * @throws Exception
     */
    protected void parseWebBundle(WebAppContext context, AnnotationParser parser, Bundle webbundle)
    throws Exception
    {
        parseBundle(context,parser,webbundle,webbundle);
    }
    
    /**
     * Scan a bundle required by the webbundle for servlet annotations
     * @param context The webapp context
     * @param parser The parser
     * @param webbundle The current webbundle
     * @param fragmentBundle The OSGi required bundle to scan
     * @throws Exception
     */
    protected void parseRequiredBundle(WebAppContext context, AnnotationParser parser,
            Bundle webbundle, Bundle requiredBundle) throws Exception
    {
        parseBundle(context,parser,webbundle,requiredBundle);
    }
    
    protected void parseBundle(WebAppContext context, AnnotationParser parser,
                               Bundle webbundle, Bundle bundle) throws Exception
                               {

        Resource bundleRes = parser.getResource(bundle);  
        Set<Handler> handlers = new HashSet<Handler>();
        handlers.addAll(_discoverableAnnotationHandlers);
        if (_classInheritanceHandler != null)
            handlers.add(_classInheritanceHandler);
        handlers.addAll(_containerInitializerAnnotationHandlers);

        ClassNameResolver classNameResolver = createClassNameResolver(context);
        if (_parserTasks != null)
        {
            BundleParserTask task = new BundleParserTask(parser, handlers, bundleRes, classNameResolver);
            _parserTasks.add(task);
            if (LOG.isDebugEnabled())
                task.setStatistic(new TimeStatistic());
        }
    }
    
    /**
     * Returns the same classname resolver than for the webInfjar scanner
     * @param context
     * @return
     */
    protected ClassNameResolver createClassNameResolver(final WebAppContext context)
    {
        return createClassNameResolver(context,true,false,false,false);
    }
    
    protected ClassNameResolver createClassNameResolver(final WebAppContext context,
            final boolean excludeSysClass, final boolean excludeServerClass, final boolean excludeEverythingElse,
            final boolean overrideIsParenLoaderIsPriority)
    {
        return new ClassNameResolver ()
        {
            public boolean isExcluded (String name)
            {
                if (context.isSystemClass(name)) return excludeSysClass;
                if (context.isServerClass(name)) return excludeServerClass;
                return excludeEverythingElse;
            }

            public boolean shouldOverride (String name)
            { 
                //looking at system classpath
                if (context.isParentLoaderPriority())
                    return overrideIsParenLoaderIsPriority;
                return !overrideIsParenLoaderIsPriority;
            }
        };
    }

}

Back to the top