001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017 package org.apache.commons.monitoring.reporting.web.handler.internal;
018
019 import org.apache.commons.monitoring.MonitoringException;
020 import org.apache.commons.monitoring.reporting.web.handler.api.Template;
021 import org.apache.commons.monitoring.reporting.web.handler.api.TemplateHelper;
022 import org.apache.commons.monitoring.reporting.web.template.MapBuilder;
023
024 import javax.servlet.http.HttpServletRequest;
025 import javax.servlet.http.HttpServletResponse;
026 import java.io.IOException;
027 import java.lang.reflect.InvocationTargetException;
028 import java.lang.reflect.Method;
029 import java.util.List;
030 import java.util.concurrent.CopyOnWriteArrayList;
031 import java.util.regex.Matcher;
032
033 public class Invoker {
034 private final Object instance;
035 private final Method method;
036 private final String name;
037 private final List<ParameterExtractor<?>> parameters = new CopyOnWriteArrayList<ParameterExtractor<?>>();
038
039 public Invoker(final Object instance, final Method method, final String name) {
040 this.instance = instance;
041 this.method = method;
042 this.name = name;
043 }
044
045 public void invoke(final HttpServletRequest request, final HttpServletResponse response, final Matcher matcher) {
046 final Object[] params = new Object[parameters.size()];
047 for (int i = 0; i < params.length; i++) {
048 params[i] = parameters.get(i).extract(request, response, matcher);
049 }
050 try {
051 final Object result = method.invoke(instance, params);
052 if (Template.class.isInstance(result)) {
053 final Template template = Template.class.cast(result);
054 final TemplateHelper helper = new TemplateHelperExtractor(name).extract(request, response, matcher);
055 if (template.isHtml()) {
056 helper.renderHtml(template.getTemplate(), template.getUserParams());
057 } else {
058 helper.renderPlain(template.getTemplate(), template.getUserParams());
059 }
060 } else if (result != null) {
061 response.getWriter().write(result.toString());
062 }
063 } catch (final InvocationTargetException e) {
064 throw new MonitoringException(e.getCause());
065 } catch (final Exception e) {
066 throw new MonitoringException(e);
067 }
068 }
069
070 public void addRequestParameter() {
071 parameters.add(new RequestExtractor());
072 }
073
074 public void addResponseParameter() {
075 parameters.add(new ResponseExtractor());
076 }
077
078 public void addTemplateHelper(final String plugin) {
079 parameters.add(new TemplateHelperExtractor(plugin));
080 }
081
082 public void addSegmentParameter(final Class<?> clazz, final int partIdx) {
083 if (String.class.equals(clazz)) {
084 parameters.add(new StringSegmentExtractor(partIdx));
085 } else if (Long.TYPE.equals(clazz)) {
086 parameters.add(new LongSegmentExtractor(partIdx));
087 } else if (Integer.TYPE.equals(clazz)) {
088 parameters.add(new IntSegmentExtractor(partIdx));
089 } else if (String[].class.equals(clazz)) {
090 parameters.add(new StringArraySegmentExtractor(partIdx));
091 } else {
092 throw new IllegalArgumentException(clazz.getName() + " not handled");
093 }
094 }
095
096 protected static interface ParameterExtractor<T> {
097 T extract(HttpServletRequest request, HttpServletResponse response, Matcher matcher);
098 }
099
100 protected static class TemplateHelperExtractor implements ParameterExtractor<TemplateHelper> {
101 private final String plugin;
102
103 public TemplateHelperExtractor(final String plugin) {
104 this.plugin = plugin;
105 }
106
107 @Override
108 public TemplateHelper extract(final HttpServletRequest request, final HttpServletResponse response, final Matcher matcher) {
109 try {
110 return new TemplateHelper(response.getWriter(), new MapBuilder<String, Object>().set("templateId", plugin).build());
111 } catch (final IOException e) {
112 throw new MonitoringException(e);
113 }
114 }
115 }
116
117 protected static class RequestExtractor implements ParameterExtractor<HttpServletRequest> {
118 @Override
119 public HttpServletRequest extract(final HttpServletRequest request, final HttpServletResponse response, final Matcher matcher) {
120 return request;
121 }
122 }
123
124 protected static class ResponseExtractor implements ParameterExtractor<HttpServletResponse> {
125 @Override
126 public HttpServletResponse extract(final HttpServletRequest request, final HttpServletResponse response, final Matcher matcher) {
127 return response;
128 }
129 }
130
131 protected static class StringSegmentExtractor implements ParameterExtractor<String> {
132 private final int index;
133
134 public StringSegmentExtractor(final int index) {
135 this.index = index;
136 }
137
138 @Override
139 public String extract(final HttpServletRequest request, final HttpServletResponse response, final Matcher matcher) {
140 return matcher.group(index);
141 }
142 }
143
144 protected static class StringArraySegmentExtractor implements ParameterExtractor<String[]> {
145 private final int index;
146
147 public StringArraySegmentExtractor(final int index) {
148 this.index = index;
149 }
150
151 @Override
152 public String[] extract(final HttpServletRequest request, final HttpServletResponse response, final Matcher matcher) {
153 return matcher.group(index).split("/");
154 }
155 }
156
157 protected static class LongSegmentExtractor implements ParameterExtractor<Long> {
158 private final int index;
159
160 public LongSegmentExtractor(final int index) {
161 this.index = index;
162 }
163
164 @Override
165 public Long extract(final HttpServletRequest request, final HttpServletResponse response, final Matcher matcher) {
166 return Long.parseLong(matcher.group(index));
167 }
168 }
169
170 protected static class IntSegmentExtractor implements ParameterExtractor<Integer> {
171 private final int index;
172
173 public IntSegmentExtractor(final int index) {
174 this.index = index;
175 }
176
177 @Override
178 public Integer extract(final HttpServletRequest request, final HttpServletResponse response, final Matcher matcher) {
179 return Integer.parseInt(matcher.group(index));
180 }
181 }
182 }