blob: 854592ed18c4fee931c9cf77b8be718eeaeb5d51 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.apache.polygene.library.restlet;
import java.io.PrintStream;
import org.apache.polygene.api.identity.HasIdentity;
import org.apache.polygene.api.injection.scope.Structure;
import org.apache.polygene.api.object.ObjectFactory;
import org.apache.polygene.api.structure.Application;
import org.apache.polygene.library.restlet.crud.EntityListResource;
import org.apache.polygene.library.restlet.crud.EntityResource;
import org.apache.polygene.library.restlet.resource.CreationResource;
import org.apache.polygene.library.restlet.resource.DefaultResourceFactoryImpl;
import org.apache.polygene.library.restlet.resource.EntryPoint;
import org.apache.polygene.library.restlet.resource.EntryPointResource;
import org.apache.polygene.library.restlet.resource.ResourceFactory;
import org.apache.polygene.library.restlet.resource.ServerResource;
import org.apache.polygene.library.restlet.serialization.PolygeneConverter;
import org.restlet.Context;
import org.restlet.Restlet;
import org.restlet.data.ChallengeScheme;
import org.restlet.data.Parameter;
import org.restlet.engine.Engine;
import org.restlet.routing.Filter;
import org.restlet.routing.Router;
import org.restlet.routing.TemplateRoute;
import org.restlet.security.ChallengeAuthenticator;
import org.restlet.security.Enroler;
import org.restlet.security.Verifier;
import org.restlet.util.Series;
/**
* This class is generic enough to be promoted to Polygene's Restlet Library
*/
@SuppressWarnings( { "WeakerAccess", "unused" } )
public abstract class PolygeneRestApplication extends org.restlet.Application
{
@Structure
protected Application polygeneApplication;
@Structure
protected ObjectFactory objectFactory;
protected Router router;
protected PolygeneRestApplication( Context context )
{
super( context );
}
protected void printRoutes( PrintStream out )
{
router.getRoutes()
.stream()
.map( Object::toString )
.forEach( out::println );
}
@Override
public synchronized void start()
throws Exception
{
setName( polygeneApplication.name() );
Series<Parameter> parameters = getContext().getParameters();
String mode = parameters.getFirstValue( "org.apache.polygene.runtime.mode" );
super.start();
getLogger().info( "RestApplication successfully started." );
}
@Override
public synchronized void stop()
throws Exception
{
super.stop();
getLogger().info( "RestApplication successfully stopped." );
}
@Override
public Restlet createInboundRoot()
{
Context context = getContext();
Engine.getInstance().getRegisteredConverters().add( new PolygeneConverter( objectFactory ) );
if( polygeneApplication.mode() == Application.Mode.development )
{
setDebugging( true );
}
router = new Router( context );
addRoutes( router );
router.attach( "/", newPolygeneRestlet( EntryPointResource.class, EntryPoint.class ) );
ChallengeAuthenticator guard = new ChallengeAuthenticator( context, ChallengeScheme.HTTP_BASIC, getName() + " Realm" );
Verifier verifier = createVerifier();
if( verifier != null )
{
guard.setVerifier( verifier );
}
Enroler enroler = createEnroler();
if( enroler != null )
{
guard.setEnroler( enroler );
}
return createInterceptors( guard );
}
private Restlet createInterceptors( ChallengeAuthenticator guard )
{
Filter inner = createInnerInterceptor();
if( inner != null )
{
inner.setNext( router );
guard.setNext( inner ); // guard -> interceptor -> router
}
else
{
guard.setNext( router ); // guard -> router
}
inner = guard; // inner = guard
Filter outer = createOuterInterceptor();
if( outer != null )
{
outer.setNext( inner ); // outer -> inner
return outer;
}
return inner;
}
protected Filter createOuterInterceptor()
{
return null;
}
protected Filter createInnerInterceptor()
{
return null;
}
protected Verifier createVerifier()
{
return null;
}
protected Enroler createEnroler()
{
return null;
}
protected abstract void addRoutes( Router router );
protected void addResourcePath( String name,
Class<? extends HasIdentity> type,
String basePath
)
{
addResourcePath( name, type, basePath, true, true );
}
protected void addResourcePath( String name,
Class<? extends HasIdentity> type,
String basePath,
boolean createLink,
boolean rootRoute
)
{
if( createLink )
{
router.attach( basePath + name + "/create", newPolygeneRestlet( CreationResource.class, type ) );
}
TemplateRoute route = router.attach( basePath + name + "/", newPolygeneRestlet( EntityListResource.class, type ) );
if( rootRoute )
{
route.setName( name );
}
router.attach( basePath + name + "/{id}/", newPolygeneRestlet( EntityResource.class, type ) );
router.attach( basePath + name + "/{id}/{invoke}", newPolygeneRestlet( EntityResource.class, type ) );
}
private <K extends HasIdentity, T extends ServerResource<K>> Restlet newPolygeneRestlet( Class<T> resourceClass, Class<K> entityClass )
{
@SuppressWarnings( "unchecked" )
ResourceFactory<K, T> factory = objectFactory.newObject( DefaultResourceFactoryImpl.class,
resourceClass, router
);
PolygeneConverter converter = new PolygeneConverter( objectFactory );
return objectFactory.newObject( PolygeneEntityRestlet.class,
factory,
router,
entityClass,
converter
);
}
}