blob: d8987e0f9625322fd4554d0304115cbac6cdc8ab [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.juneau.rest;
import java.util.*;
import javax.servlet.*;
import org.apache.juneau.rest.annotation.*;
import org.apache.juneau.rest.util.*;
/**
* Implements the child resources of a {@link Rest}-annotated class.
*/
public class RestChildren {
/**
* Represents a null value for the {@link Rest#restChildrenClass()} annotation.
*/
@SuppressWarnings("javadoc")
public final class Null extends RestChildren {
public Null(RestChildrenBuilder builder) throws Exception {
super(builder);
}
}
private final Map<String,RestContext> children = Collections.synchronizedMap(new LinkedHashMap<String,RestContext>());
/**
* Creates a new builder for this object.
*
* @return A new builder for this object.
*/
public static RestChildrenBuilder create() {
return new RestChildrenBuilder();
}
/**
* Constructor.
*
* @param builder The builder containing the settings for this object.
*/
public RestChildren(RestChildrenBuilder builder) {
for (RestContext rc : builder.list)
children.put(rc.getPath(), rc);
}
/**
* Looks through the registered children of this object and returns the best match.
*
* @param call The HTTP call.
* @return The child that best matches the call, or an empty {@link Optional} if a match could not be made.
*/
public Optional<RestChildMatch> findMatch(RestCall call) {
String pi = call.getPathInfoUndecoded();
if ((! children.isEmpty()) && pi != null && ! pi.equals("/")) {
for (RestContext rc : children.values()) {
UrlPathMatcher upp = rc.getPathMatcher();
UrlPathMatch uppm = upp.match(call.getUrlPath());
if (uppm != null) {
return Optional.of(RestChildMatch.create(uppm, rc));
}
}
}
return Optional.empty();
}
/**
* Returns the children in this object as a map.
*
* <p>
* The keys are the {@link RestContext#getPath() paths} of the child contexts.
*
* @return The children as an unmodifiable map.
*/
public Map<String,RestContext> asMap() {
return Collections.unmodifiableMap(children);
}
//-----------------------------------------------------------------------------------------------------------------
// Lifecycle methods.
//-----------------------------------------------------------------------------------------------------------------
/**
* Called during servlet initialization on all children to invoke all {@link HookEvent#POST_INIT} methods.
*
* @throws ServletException Error occurred.
*/
public void postInit() throws ServletException {
for (RestContext childContext : children.values())
childContext.postInit();
}
/**
* Called during servlet initialization on all children to invoke all {@link HookEvent#POST_INIT_CHILD_FIRST} methods.
*
* @throws ServletException Error occurred.
*/
public void postInitChildFirst() throws ServletException {
for (RestContext childContext : children.values())
childContext.postInitChildFirst();
}
/**
* Called during servlet destruction on all children to invoke all {@link HookEvent#DESTROY} and {@link Servlet#destroy()} methods.
*/
public void destroy() {
for (RestContext r : children.values()) {
r.destroy();
if (r.getResource() instanceof Servlet)
((Servlet)r.getResource()).destroy();
}
}
}