/**
* Copyright 2017 Linagora, Université Joseph Fourier, Floralis
*
* The present code is developed in the scope of the joint LINAGORA -
* Université Joseph Fourier - Floralis research program and is designated
* as a "Result" pursuant to the terms and conditions of the LINAGORA
* - Université Joseph Fourier - Floralis research program. Each copyright
* holder of Results enumerated here above fully & independently holds complete
* ownership of the complete Intellectual Property rights applicable to the whole
* of said Results, and may freely exploit it in any manner which does not infringe
* the moral rights of the other copyright holders.
*
* 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.
*/
package net.roboconf.dm.rest.services.internal.annotations;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import net.roboconf.dm.rest.services.internal.RestApplication;
/**
* @author Vincent Zurczak - Linagora
*/
public class RestIndexer {
public final List<RestOperationBean> restMethods = new ArrayList<> ();
private final Logger logger = Logger.getLogger( getClass().getName());
/**
* Constructor.
*/
public RestIndexer() {
boolean duplicates = false;
final Map<String,String> patternToResourceName = new HashMap<> ();
for( Class<?> clazz : RestApplication.getResourceClasses()) {
// Get the root path (set on the class itself)
String basePath = "";
if( clazz.isAnnotationPresent( Path.class )) {
Path pathAnnotation = clazz.getAnnotation( Path.class );
basePath = pathAnnotation.value();
}
// Other parts are declared in our super interfaces
Class<?> superClass = clazz.getInterfaces()[ 0 ];
for( Method m : superClass.getMethods()) {
String restVerb = null;
if( m.isAnnotationPresent( POST.class ))
restVerb = "POST";
else if( m.isAnnotationPresent( GET.class ))
restVerb = "GET";
else if( m.isAnnotationPresent( DELETE.class ))
restVerb = "DELETE";
else if( m.isAnnotationPresent( PUT.class ))
restVerb = "PUT";
if( restVerb == null )
continue;
//if( ! m.isAnnotationPresent( Auth.class ))
// continue;
String subPath = "";
if( m.isAnnotationPresent( Path.class )) {
Path pathAnnotation = m.getAnnotation( Path.class );
subPath = pathAnnotation.value();
}
RestOperationBean restOperationBean = new RestOperationBean();
restOperationBean.methodName = m.getName();
restOperationBean.restVerb = restVerb;
restOperationBean.jerseyPath = basePath + subPath;
restOperationBean.urlPattern = restOperationBean.jerseyPath.replaceAll( "\\{[^}]+\\}", "[^/]+" );
this.restMethods.add( restOperationBean );
// Duplicate URL patterns?
String key = restVerb + "_" + restOperationBean.urlPattern;
String assoc = patternToResourceName.get( key );
if( assoc != null ) {
duplicates = true;
this.logger.severe( "Duplicate pattern: " + key + " = " + assoc );
} else {
patternToResourceName.put( key, clazz.getSimpleName() + "_" + m.getName());
}
}
}
// Throw an exception if duplicates were found, as our permission and audit
// systems are based on this class.
if( duplicates ) {
// Inconsistencies are located in the code.
// They should appear during tests and before we release.
this.logger.severe( "REST methods contain inconsistencies. Audit and permissions checking are currently NOT reliable." );
throw new RuntimeException( "Duplicates were found in URL patterns." );
}
}
/**
* @author Vincent Zurczak - Linagora
*/
public static class RestOperationBean {
private String methodName, urlPattern, jerseyPath, restVerb;
/**
* @return the methodName
*/
public String getMethodName() {
return this.methodName;
}
/**
* @return the urlPattern
*/
public String getUrlPattern() {
return this.urlPattern;
}
/**
* @return the jerseyPath
*/
public String getJerseyPath() {
return this.jerseyPath;
}
/**
* @return the restVerb
*/
public String getRestVerb() {
return this.restVerb;
}
@Override
public String toString() {
return this.methodName;
}
}
}