/*
* #%L restdoc-doclet %% Copyright (C) 2012 IG Group %% Licensed under the
* Apache 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://www.apache.org/licenses/LICENSE-2.0 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. #L%
*/
package com.iggroup.oss.restdoclet.doclet.util;
import static com.iggroup.oss.restdoclet.doclet.util.AnnotationUtils.isAnnotated;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Properties;
import org.apache.log4j.PropertyConfigurator;
import com.iggroup.oss.restdoclet.doclet.type.Controller;
import com.iggroup.oss.restdoclet.doclet.type.FieldParameter;
import com.iggroup.oss.restdoclet.doclet.type.builder.FieldParameterBuilder;
import com.sun.javadoc.ClassDoc;
import com.sun.javadoc.FieldDoc;
import com.sun.javadoc.MethodDoc;
/**
* Manages properties of <code>doclet</code> module. This class also contains
* utility operations.
*/
public final class DocletUtils {
/**
* The name of the file that contains the properties. This file is packaged
* with <code>doclet</code>'s archive.
*/
public static final String PROPERTIES_FILE =
"oss-restdoclet-doclet.properties";
private static final String GETTER_PREFIX = "get";
/**
* Environment variable to control restdoc logging
*/
private static final String RESTDOCLET_LOGGING = "RESTDOCLET_LOGGING";
/**
* The property containing the artifact-identifier of <code>doclet</code>
* module.
*/
public static final String ARTIFACT_ID = "project.artifactId";
/**
* The singleton instance of this class.
*/
private static DocletUtils instance;
/**
* The properties of <code>doclet</code> module.
*/
private final Properties properties;
/**
* Constructs the singleton instance of this class.
*
* @throws IOException if <code>doclet</code>'s properties can't be read.
*/
private DocletUtils() throws IOException {
super();
properties = new Properties();
properties.load(Thread.currentThread().getContextClassLoader()
.getResourceAsStream(PROPERTIES_FILE));
}
/**
* Gets the singleton instance of this class.
*
* @return the singleton instance of this class.
* @throws IOException if <code>doclet</code>'s properties can't be read.
*/
public static DocletUtils getInstance() throws IOException {
synchronized (PROPERTIES_FILE) {
if (instance == null) {
instance = new DocletUtils();
}
return instance;
}
}
/**
* Gets the properties of <code>doclet</code> module.
*
* @return <code>doclet</code>'s properties.
*/
public Properties getProperties() {
return properties;
}
/**
* Sets the properties of <code>doclet</code> module. This operation is not
* supported.
*
* @param properties <code>doclet</code>'s properties.
*/
public void setProperties(final Properties properties) {
throw new UnsupportedOperationException(
"DocletUtils.setProperties(Properties)");
}
/**
* Gets the artifact-identifier of <code>doclet</code> module.
*
* @return the artifact-identifier.
* @throws IOException if <code>doclet</code>'s properties can't be read.
*/
public static String artifactIdentifier() throws IOException {
return getInstance().properties.getProperty(ARTIFACT_ID);
}
/**
* Determines if a class is Spring's controller.
*
* @param classDoc the Java documentation object of the class.
* @return <code>true</code> if the class is a Spring's controller,
* <code>false</code> otherwise.
*/
public static boolean isController(final ClassDoc classDoc) {
return isAnnotated(classDoc,
org.springframework.stereotype.Controller.class);
}
/**
* Gets the file containing the documentation of a class.
*
* @param classDoc the Java documentation object of the class.
* @return the file containing documentation.
*/
public static File documentationFile(final ClassDoc classDoc) {
final StringBuffer path = new StringBuffer();
path.append(classDoc.qualifiedName().replace('.', File.separatorChar));
if (isController(classDoc)) {
path.append(Controller.FILE_SUFFIX);
} else {
path.append(".class.xml");
}
final File doc = new File(path.toString());
doc.getParentFile().mkdirs();
return doc;
}
/**
* Return a list of all fields that have a public getter
*
* @param classDoc class documentation
* @return list of all fields that have a public getter
*/
public static Collection<FieldParameter> getPublicFields(final ClassDoc classDoc) {
ArrayList<FieldParameter> fields = new ArrayList<FieldParameter>();
MethodDoc[] methods = classDoc.methods();
for (FieldDoc fieldDoc : classDoc.fields(false)) {
boolean found = false;
for (MethodDoc md : methods) {
if (md.name().equalsIgnoreCase(GETTER_PREFIX + fieldDoc.name())) {
found = true;
}
}
if (found) {
fields.add(new FieldParameterBuilder().build(new FieldParameter(),
fieldDoc));
}
}
return fields;
}
/**
* Initialise log4j based on RESTDOC_DEBUG environment variable
*/
public static void initialiseLogging() {
String debugLevel = System.getProperty(RESTDOCLET_LOGGING);
if (debugLevel != null
&& (debugLevel.equalsIgnoreCase("debug")
|| debugLevel.equalsIgnoreCase("info") || debugLevel
.equalsIgnoreCase("error"))) {
System.out.println("Setting RESTDoclet logging level to : "
+ debugLevel);
try {
Properties logProperties = new Properties();
InputStream is =
DocletUtils.class.getClassLoader().getResourceAsStream(
"log4j.properties." + debugLevel.toLowerCase());
if (is == null) {
System.err
.println("[ERROR] Failed to load file : log4j.properties."
+ debugLevel.toLowerCase());
} else {
logProperties.load(is);
PropertyConfigurator.configure(logProperties);
}
} catch (Exception ioe) {
System.err
.println("[ERROR] - Failed to initialised RESTDoclet doclet logging");
ioe.printStackTrace();
}
}
}
/**
* Preserve the formatting of the javadoc string
*
* @param javadoc
* @return javadoc string wrapped with span element of type javadoc
*/
public static String preserveJavadocFormatting(final String javadoc) {
if (javadoc.contains("<span class=\"javadoc\">")) {
return javadoc;
}
return "<span class=\"javadoc\">" + javadoc + "</span>";
}
public static MethodDoc findMethodDocumentation(final MethodDoc methodDoc) {
// Look in parent class for javadoc
if (methodDoc.commentText().contains("@inheritDoc")) {
ClassDoc containingClass = methodDoc.containingClass();
ClassDoc superClass = containingClass.superclass().asClassDoc();
for (MethodDoc md : superClass.methods()) {
if (md.name().equalsIgnoreCase(methodDoc.name())
&& md.signature().equalsIgnoreCase(methodDoc.signature())) {
return md;
}
}
// Look in interfaces for javadoc
for (ClassDoc cd : containingClass.interfaces()) {
for (MethodDoc md : cd.methods()) {
if (md.name().equalsIgnoreCase(methodDoc.name())
&& md.signature().equalsIgnoreCase(methodDoc.signature())) {
return md;
}
}
}
}
return methodDoc;
}
}