1 package org.apache.velocity.site.doxia.renderer;
2
3 /*
4 * Licensed to the Apache Software Foundation (ASF) under one
5 * or more contributor license agreements. See the NOTICE file
6 * distributed with this work for additional information
7 * regarding copyright ownership. The ASF licenses this file
8 * to you under the Apache License, Version 2.0 (the
9 * "License"); you may not use this file except in compliance
10 * with the License. You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing,
15 * software distributed under the License is distributed on an
16 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 * KIND, either express or implied. See the License for the
18 * specific language governing permissions and limitations
19 * under the License.
20 */
21
22 import java.io.Reader;
23 import java.io.StringReader;
24 import java.lang.reflect.Method;
25
26 import org.apache.maven.doxia.parser.AbstractParser;
27 import org.apache.maven.doxia.parser.ParseException;
28 import org.apache.maven.doxia.parser.Parser;
29 import org.apache.maven.doxia.sink.Sink;
30 import org.apache.velocity.site.doxia.plugin.DoxiaVelocityRendererPlugin;
31 import org.apache.velocity.site.doxia.runner.DefaultVelocityRunner;
32 import org.apache.velocity.site.doxia.runner.VelocityRunner;
33 import org.apache.velocity.site.plexus.PlexusKludgeException;
34 import org.apache.velocity.site.plexus.PlexusKludgeUtils;
35 import org.codehaus.plexus.PlexusConstants;
36 import org.codehaus.plexus.PlexusContainer;
37 import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
38 import org.codehaus.plexus.context.Context;
39 import org.codehaus.plexus.context.ContextException;
40 import org.codehaus.plexus.personality.plexus.lifecycle.phase.Contextualizable;
41
42 /**
43 * <p>
44 * This is the base class for the various parsers. This does not run inside the
45 * Mojo API and the plugin cycle but gets instantiated by Plexus itself.
46 * </p>
47 *
48 * <p>
49 * <b>NOTE:</b> This parser could be so much easier if it were possible to
50 * inject the ParserManager. Then only one instance would be needed and the
51 * class could decide whether the supplied input was XDoc or APT or something
52 * else. However, Plexus chokes on cyclic definitions (The Parsers are injected
53 * into the ParserManager which in turn should be injected into one Parser).
54 * Maybe the Plexus authors should do less Spring bashing (Spring gets this
55 * right) and fix their injectors...
56 * </p>
57 *
58 * @author <a href="mailto:henning@apache.org">Henning P. Schmiedehausen</a>
59 * @version $Revision: 526751 $
60 */
61 public abstract class AbstractVelocityRenderer extends AbstractParser implements Contextualizable
62
63 {
64 protected PlexusContainer container = null;
65
66 private final String roleHint;
67
68 /**
69 * Creates a new AbstractVelocityRenderer object.
70 */
71 protected AbstractVelocityRenderer(final String roleHint)
72 {
73 this.roleHint = roleHint;
74 }
75
76 public void contextualize(final Context context) throws ContextException
77 {
78 this.container = (PlexusContainer) context.get(PlexusConstants.PLEXUS_KEY);
79 }
80
81 /**
82 * Returns the actual Parser (currently only Apt and Xdoc) must be injected
83 * into an instance of this component. This is where the Xdoc and the Apt
84 * parser differ.
85 *
86 * @return A {@link Parser} instance that is the actual parser for this
87 * document type once Velocity processed the template.
88 */
89 protected Parser getParser() throws ComponentLookupException
90 {
91 return (Parser) container.lookup(Parser.ROLE, roleHint);
92 }
93
94 /**
95 * This is the actual parsing stage. We fetch the Runner object from the
96 * doxia-renderer plugin and execute the parse method on it.
97 *
98 * @param reader
99 * The reader which returns the actual template data.
100 * @param sink
101 * The Doxia Sink to send our information to.
102 *
103 * @throws parseException
104 * When Velocity can not load or process the template.
105 */
106 public final synchronized void parse(final Reader reader, final Sink sink) throws ParseException
107 {
108 try
109 {
110 Object runner = getVelocityRunner();
111 Method parseVelocity = runner.getClass().getMethod(VelocityRunner.PARSE_METHOD, VelocityRunner.PARSE_METHOD_SIGNATURE);
112 String result = (String) parseVelocity.invoke(runner, new Object[] { reader });
113
114 StringReader strReader = new StringReader(result);
115
116 getParser().parse(strReader, sink);
117 }
118 catch (RuntimeException re)
119 {
120 throw re;
121 }
122 catch (Exception e)
123 {
124 throw new ParseException(e);
125 }
126 }
127
128 /**
129 * Returns the Velocity Context factory which contains the values set by the
130 * Plugin for the Velocity renderer.
131 *
132 * It must be injected into an instance of this component.
133 *
134 * @return A {@link DoxiaVelocityContextFactory} instance that generates
135 * {@link VelocityContext} objects for the render process.
136 */
137 private Object getVelocityRunner() throws ComponentLookupException
138 {
139 try
140 {
141 PlexusContainer velocityContainer = PlexusKludgeUtils.lookupContainer(container,
142 DoxiaVelocityRendererPlugin.CONTAINER_LOOKUP_NAME);
143 return velocityContainer.lookup(DefaultVelocityRunner.ROLE);
144 }
145 catch (PlexusKludgeException pke)
146 {
147 throw new ComponentLookupException("While retrieving Velocity runner: ", pke);
148 }
149 }
150 }