org.opencastproject.runtimeinfo.Activator Maven / Gradle / Ivy
/**
* Licensed to The Apereo Foundation under one or more contributor license
* agreements. See the NOTICE file distributed with this work for additional
* information regarding copyright ownership.
*
*
* The Apereo Foundation licenses this file to you under the Educational
* Community License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of the License
* at:
*
* http://opensource.org/licenses/ecl2.txt
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*
*/
package org.opencastproject.runtimeinfo;
import static org.opencastproject.rest.RestConstants.SERVICES_FILTER;
import static org.opencastproject.rest.RestConstants.SERVICE_PATH_PROPERTY;
import static org.opencastproject.util.data.Option.none;
import static org.opencastproject.util.data.Option.some;
import org.opencastproject.runtimeinfo.rest.RestDocData;
import org.opencastproject.systems.OpencastConstants;
import org.opencastproject.util.data.Option;
import org.opencastproject.util.doc.DocUtil;
import org.opencastproject.util.doc.rest.RestQuery;
import org.opencastproject.util.doc.rest.RestService;
import org.apache.commons.lang3.StringUtils;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceReference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
import javax.servlet.Servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.HttpMethod;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
/** A bundle activator that registers the REST documentation servlet. */
public class Activator extends HttpServlet implements BundleActivator {
/** The logger */
private static final Logger logger = LoggerFactory.getLogger(Activator.class);
/** The query string parameter used to specify a specific service */
private static final String PATH_PARAM = "path";
/** java.io serialization UID */
private static final long serialVersionUID = 6930336096831297329L;
/** The OSGI bundle context */
protected BundleContext bundleContext;
/** A map of global macro values for REST documentation. */
private Map globalMacro;
@Override
public void start(BundleContext bundleContext) throws Exception {
this.bundleContext = bundleContext;
Dictionary props = new Hashtable();
props.put("alias", "/docs.html");
prepareMacros();
bundleContext.registerService(Servlet.class.getName(), this, props);
}
/** Add a list of global information, such as the server URL, to the globalMacro map. */
private void prepareMacros() {
globalMacro = new HashMap();
globalMacro.put("PING_BACK_URL", bundleContext.getProperty("org.opencastproject.anonymous.feedback.url"));
globalMacro.put("HOST_URL", bundleContext.getProperty(OpencastConstants.SERVER_URL_PROPERTY));
globalMacro.put("LOCAL_STORAGE_DIRECTORY", bundleContext.getProperty("org.opencastproject.storage.dir"));
}
@Override
public void stop(BundleContext bundleContext) throws Exception {
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String docPath = req.getParameter(PATH_PARAM);
if (StringUtils.isBlank(docPath)) {
resp.sendRedirect("rest_docs.html");
} else {
// write the details for this service
writeServiceDocumentation(docPath, resp);
}
}
private void writeServiceDocumentation(final String docPath, HttpServletResponse resp)
throws IOException {
ServiceReference reference = null;
for (ServiceReference ref : getRestEndpointServices()) {
String alias = (String) ref.getProperty(SERVICE_PATH_PROPERTY);
if (docPath.equalsIgnoreCase(alias)) {
reference = ref;
break;
}
}
final StringBuilder docs = new StringBuilder();
if (reference == null) {
docs.append("REST docs unavailable for ");
docs.append(docPath);
} else {
final Object restService = bundleContext.getService(reference);
findRestAnnotation(restService.getClass()).fold(new Option.Match() {
@Override
public Void some(RestService annotation) {
globalMacro.put("SERVICE_CLASS_SIMPLE_NAME", restService.getClass().getSimpleName());
RestDocData data = new RestDocData(annotation.name(), annotation.title(), docPath, annotation.notes());
data.setAbstract(annotation.abstractText());
Produces producesClass = (Produces) restService.getClass().getAnnotation(Produces.class);
for (Method m : restService.getClass().getMethods()) {
RestQuery rq = (RestQuery) m.getAnnotation(RestQuery.class);
String httpMethodString = null;
for (Annotation a : m.getAnnotations()) {
HttpMethod httpMethod = (HttpMethod) a.annotationType().getAnnotation(HttpMethod.class);
if (httpMethod != null) {
httpMethodString = httpMethod.value();
}
}
Produces produces = (Produces) m.getAnnotation(Produces.class);
if (produces == null) {
produces = producesClass;
}
Path path = (Path) m.getAnnotation(Path.class);
Class> returnType = m.getReturnType();
if ((rq != null) && (httpMethodString != null) && (path != null)) {
data.addEndpoint(rq, returnType, produces, httpMethodString, path);
}
}
String template = DocUtil.loadTemplate("/ui/restdocs/template.xhtml");
docs.append(DocUtil.generate(data, template));
return null;
}
@Override
public Void none() {
docs.append("No documentation has been found for ").append(restService.getClass().getSimpleName());
return null;
}
});
}
resp.setContentType("text/html");
resp.getWriter().write(docs.toString());
}
private ServiceReference[] getRestEndpointServices() {
try {
return bundleContext.getAllServiceReferences(null, SERVICES_FILTER);
} catch (InvalidSyntaxException e) {
logger.warn("Unable to query the OSGI service registry for all registered rest endpoints");
return new ServiceReference[0];
}
}
/** Try to find the RestService annotation starting at endpointClass
. */
public static Option findRestAnnotation(Class> endpointClass) {
if (endpointClass == null) {
return none();
}
final RestService rs = endpointClass.getAnnotation(RestService.class);
if (rs == null) {
return findRestAnnotation(endpointClass.getSuperclass());
} else {
return some(rs);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy