All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.wicketstuff.annotation.scan.AnnotatedMountScanner Maven / Gradle / Ivy

Go to download

Use wicketstuff-annotation to use Java Annotations and class path searching to mount your Wicket pages.

There is a newer version: 10.2.0
Show newest version
/*
 * 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.wicketstuff.annotation.scan;

import java.util.List;

import org.apache.wicket.Application;
import org.apache.wicket.Page;
import org.apache.wicket.core.request.mapper.HomePageMapper;
import org.apache.wicket.request.IRequestMapper;
import org.apache.wicket.request.component.IRequestablePage;
import org.apache.wicket.core.request.mapper.MountedMapper;
import org.wicketstuff.annotation.mount.MountPath;
import org.wicketstuff.config.MatchingResources;

/**
 * Looks for mount information by scanning for classes annotated with {@link MountPath}. You can
 * specify a package to scan (e.g., "org.mycompany.wicket.pages"). Wildcards also work (e.g.,
 * "org.mycompany.*.pages" or "org.mycompany.**.pages").
 * 
 * 

* You can also go more advanced, using any pattern supported by {@link MatchingResources}. For * example, the first package example above is turned into * "classpath*:/org/mycompany/wicket/pages/**/*.class". * *

* For each class that is annotated, an appropriate {@link IRequestMapper} implementing class is * created using the information in the {@link MountPath} annotation and any supplemental * annotations. Each instance is added to the list to return. Each item in the returned list can * then be mounted. * *

* Typical usage is in your {@link Application#init()} method and utilizes the * {@link AnnotatedMountList#mount} convenience method. * *

 * protected void init()
 * {
 * 	new AnnotatedMountScanner().scanPackage("org.mycompany.wicket.pages").mount(this);
 * }
 * 
* *

* You could scan the entire classpath if you wanted by passing in null, but that might require more * time to run than limiting it to known packages which have annotated classes. * *

* Page classes annotation usage is as follows: * *

 * @MountPath
 * private class HelloPage extends Page
 * {
 * }
 * 
 * @MountPath("hello")
 * private class HelloPage extends Page
 * {
 * }
 * 
 * @MountPath(value = "dogs", alt = { "canines", "k9s" })
 * private class DogsPage extends Page
 * {
 * }
 * 
* *

* The first example will mount HelloPage to /HelloPage using the default mapper (as returned by * {@link #getRequestMapper} which is {@link MountedMapper}. * *

* The second example will mount HelloPage to /hello using the default mapper (as returned by * {@link #getRequestMapper} which is {@link MountedMapper}. * *

* The third example will mount DogsPage at "/dogs" (as the primary) and as "/canines" and "/k9s" as * alternates using the {@link MountedMapper}. * * @author Doug Donohoe * @author Ronald Tetsuo Miura */ public class AnnotatedMountScanner { /** * Get the Spring search pattern given a package name or part of a package name * * @param packageName * a package name * @return a Spring search pattern for the given package */ public String getPatternForPackage(String packageName) { if (packageName == null) packageName = ""; packageName = packageName.replace('.', '/'); if (!packageName.endsWith("/")) { packageName += '/'; } return "classpath*:" + packageName + "**/*.class"; } /** * Scan given a package name or part of a package name and return list of classes with MountPath * annotation. * * @return A List of classes annotated with @MountPath */ public List> getPackageMatches(String pattern) { return getPatternMatches(getPatternForPackage(pattern)); } /** * Scan given a Spring search pattern and return list of classes with MountPath annotation. * * @return A List of classes annotated with @MountPath */ public List> getPatternMatches(String pattern) { MatchingResources resources = new MatchingResources(pattern); List> mounts = resources.getAnnotatedMatches(MountPath.class); for (Class mount : mounts) { if (!(Page.class.isAssignableFrom(mount))) { throw new RuntimeException("@MountPath annotated class should subclass Page: " + mount); } } return mounts; } /** * Scan given package name or part of a package name * * @param packageName * a package to scan (e.g., "org.mycompany.pages) * @return An {@link AnnotatedMountList} */ public AnnotatedMountList scanPackage(String packageName) { return scanList(getPackageMatches(packageName)); } /** * Scan given a Spring search pattern. * * @param pattern * @return An {@link AnnotatedMountList} */ public AnnotatedMountList scanPattern(String pattern) { return scanList(getPatternMatches(pattern)); } /** * Scan a list of classes which are annotated with MountPath * * @param mounts * @return An {@link AnnotatedMountList} */ @SuppressWarnings({ "unchecked" }) protected AnnotatedMountList scanList(List> mounts) { AnnotatedMountList list = new AnnotatedMountList(); for (Class mount : mounts) { Class page = (Class)mount; scanClass(page, list); } return list; } /** * Scan given a class that is a sublass of {@link Page}. * * @param pageClass * {@link Page} subclass to scan * @return An {@link AnnotatedMountList} containing the primary and alternate strategies created * for the class. */ public AnnotatedMountList scanClass(Class pageClass) { AnnotatedMountList list = new AnnotatedMountList(); scanClass(pageClass, list); return list; } /** * Magic of all this is done here. * * @param pageClass * @param list */ private void scanClass(Class pageClass, AnnotatedMountList list) { MountPath mountPath = pageClass.getAnnotation(MountPath.class); if (mountPath == null) return; // alternates for (String alt : mountPath.alt()) { list.add(getRequestMapper(alt, pageClass)); } String path = mountPath.value(); // default if no explicit path is provided if ("".equals(path)) { path = getDefaultMountPath(pageClass); } list.add(getRequestMapper(path, pageClass)); } /** * Returns the default mapper given a mount path and class. * * @param mountPath * @param pageClass * @return {@link MountedMapper} */ public IRequestMapper getRequestMapper(String mountPath, Class pageClass) { if ("/".equals(mountPath)) { return new HomePageMapper(pageClass); } return new MountedMapper(mountPath, pageClass); } /** * Returns the default mount path for a given class (used if the path has not been specified in * the @MountPath annotation). By default, this method returns the * pageClass.getSimpleName(). * * @param pageClass * @return the default mount path for pageClass */ public String getDefaultMountPath(Class pageClass) { return pageClass.getSimpleName(); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy