~mwhudson/hudson/2.x

« back to all changes in this revision

Viewing changes to hudson-inject/src/main/java/com/sonatype/matrix/smoothie/injecto/internal/XStreamInjectoHandler.java

  • Committer: Jason van Zyl
  • Date: 2011-02-17 14:40:01 UTC
  • mfrom: (9408.1.3)
  • Revision ID: git-v1:06a570a521abbbe3a889b27f8fcb6445a39246bf
Merge remote branch 'mcculls-jsr330/JSR330' into JSR330

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/**
 
2
 * The MIT License
 
3
 *
 
4
 * Copyright (c) 2010 Sonatype, Inc. All rights reserved.
 
5
 *
 
6
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 
7
 * of this software and associated documentation files (the "Software"), to deal
 
8
 * in the Software without restriction, including without limitation the rights
 
9
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 
10
 * copies of the Software, and to permit persons to whom the Software is
 
11
 * furnished to do so, subject to the following conditions:
 
12
 *
 
13
 * The above copyright notice and this permission notice shall be included in
 
14
 * all copies or substantial portions of the Software.
 
15
 *
 
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 
17
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 
19
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 
20
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 
21
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 
22
 * THE SOFTWARE.
 
23
 */
 
24
 
 
25
package com.sonatype.matrix.smoothie.injecto.internal;
 
26
 
 
27
import com.sonatype.matrix.smoothie.injecto.Injectomatic;
 
28
import com.thoughtworks.xstream.XStream;
 
29
import com.thoughtworks.xstream.converters.UnmarshallingContext;
 
30
import com.thoughtworks.xstream.converters.reflection.ReflectionProvider;
 
31
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
 
32
import com.thoughtworks.xstream.mapper.Mapper;
 
33
import hudson.XmlFile;
 
34
import hudson.model.Hudson;
 
35
import hudson.model.Items;
 
36
import hudson.model.Queue;
 
37
import hudson.model.Run;
 
38
import hudson.model.UpdateCenter;
 
39
import hudson.util.RobustReflectionConverter;
 
40
import org.slf4j.Logger;
 
41
import org.slf4j.LoggerFactory;
 
42
import org.sonatype.inject.EagerSingleton;
 
43
 
 
44
import javax.inject.Inject;
 
45
import javax.inject.Named;
 
46
import java.lang.reflect.Field;
 
47
 
 
48
/**
 
49
 * Handles {@link com.sonatype.matrix.smoothie.injecto.Injectomatic} muck when unmarshalling components via XStream.
 
50
 *
 
51
 * @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
 
52
 * @since 0.2
 
53
 */
 
54
@Named
 
55
@EagerSingleton
 
56
public class XStreamInjectoHandler
 
57
{
 
58
    private static final Logger log = LoggerFactory.getLogger(XStreamInjectoHandler.class);
 
59
 
 
60
    /**
 
61
     * {@link XmlFile#DEFAULT_XSTREAM} is not public, so we have to use reflection to get a hold of it :-(
 
62
     */
 
63
    private static final XStream XmlFile_DEFAULT_XSTREAM;
 
64
 
 
65
    static {
 
66
        try {
 
67
            Field field = XmlFile.class.getDeclaredField("DEFAULT_XSTREAM");
 
68
            field.setAccessible(true);
 
69
            XmlFile_DEFAULT_XSTREAM = (XStream) field.get(null);
 
70
        }
 
71
        catch (Exception e) {
 
72
            throw new Error(e);
 
73
        }
 
74
    }
 
75
 
 
76
    /**
 
77
     * Set of XStream instances which registration converters will be attached.
 
78
     */
 
79
    private static final XStream[] DEFAULT_XSTREAMS = {
 
80
        Hudson.XSTREAM,
 
81
        Items.XSTREAM,
 
82
        Queue.XSTREAM,
 
83
        Run.XSTREAM,
 
84
        UpdateCenter.XSTREAM,
 
85
        XmlFile_DEFAULT_XSTREAM
 
86
    };
 
87
 
 
88
    private final Injectomatic injecto;
 
89
 
 
90
    private final ReflectionProvider reflection;
 
91
 
 
92
    @Inject
 
93
    public XStreamInjectoHandler(final Injectomatic injecto, final ReflectionProvider reflection) {
 
94
        assert injecto != null;
 
95
        this.injecto = injecto;
 
96
        assert reflection != null;
 
97
        this.reflection = reflection;
 
98
 
 
99
        // Register converter for the default streams we know about
 
100
        for (XStream xs : DEFAULT_XSTREAMS) {
 
101
            register(xs);
 
102
        }
 
103
    }
 
104
 
 
105
    public void register(final XStream xs) {
 
106
        assert xs != null;
 
107
        log.trace("Registering converter for: {}", xs);
 
108
        xs.registerConverter(new InjectoConverter(xs.getMapper(), reflection), XStream.PRIORITY_VERY_LOW);
 
109
    }
 
110
 
 
111
    /**
 
112
     * Handles injecto muck when unmarshalling.  Extends from {@link RobustReflectionConverter} to
 
113
     * make use of Hudson's old/unreadable data handling.
 
114
     */
 
115
    private class InjectoConverter
 
116
        extends RobustReflectionConverter
 
117
    {
 
118
        public InjectoConverter(final Mapper mapper, final ReflectionProvider provider) {
 
119
            super(mapper, provider);
 
120
        }
 
121
 
 
122
        public boolean canConvert(final Class type) {
 
123
            return injecto.isInjectable(type);
 
124
        }
 
125
 
 
126
        @Override
 
127
        public Object doUnmarshal(Object result, final HierarchicalStreamReader reader, final UnmarshallingContext context) {
 
128
            result = super.doUnmarshal(result, reader, context);
 
129
            log.trace("Injecting instance of Describable from converter");
 
130
            injecto.inject(result);
 
131
            return result;
 
132
        }
 
133
    }
 
134
}
 
 
b'\\ No newline at end of file'