1 package org.codehaus.mojo.gwt.webxml;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.io.IOException;
23 import java.util.LinkedHashSet;
24 import java.util.Map;
25 import java.util.Set;
26
27 import org.apache.commons.lang.StringUtils;
28 import org.codehaus.plexus.component.annotations.Component;
29 import org.codehaus.plexus.logging.AbstractLogEnabled;
30 import org.springframework.core.io.Resource;
31 import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
32 import org.springframework.core.io.support.ResourcePatternResolver;
33 import org.springframework.core.type.classreading.MetadataReader;
34 import org.springframework.core.type.classreading.MetadataReaderFactory;
35 import org.springframework.core.type.classreading.SimpleMetadataReaderFactory;
36 import org.springframework.core.type.AnnotationMetadata;
37 import org.springframework.core.type.ClassMetadata;
38 import org.springframework.util.ClassUtils;
39
40 import com.google.gwt.user.client.rpc.RemoteServiceRelativePath;
41
42
43
44
45
46
47
48
49
50
51 @Component(role = ServletAnnotationFinder.class)
52 public class ServletAnnotationFinder
53 extends AbstractLogEnabled
54 {
55
56 public ServletAnnotationFinder()
57 {
58
59 }
60
61 private MetadataReader getMetadataReader(String className,
62 MetadataReaderFactory factory,
63 PathMatchingResourcePatternResolver resourceResolver)
64 throws IOException
65 {
66 String resourcePath = ClassUtils.convertClassNameToResourcePath(className);
67 Resource resource = resourceResolver.getResource(resourcePath + ".class");
68 if (resource.exists()) {
69 return factory.getMetadataReader(resource);
70 }
71 return null;
72 }
73
74 private boolean extendsRemoteServlet(ClassMetadata classMetadata,
75 MetadataReaderFactory factory,
76 PathMatchingResourcePatternResolver resourceResolver)
77 throws IOException
78 {
79 if (classMetadata.hasSuperClass()) {
80 String name = classMetadata.getSuperClassName();
81 if (name.equals("com.google.gwt.user.server.rpc.RemoteServiceServlet")) {
82 return true;
83 }
84 MetadataReader r = getMetadataReader(classMetadata.getSuperClassName(), factory, resourceResolver);
85 return extendsRemoteServlet(r.getClassMetadata(), factory, resourceResolver);
86 }
87 return false;
88 }
89
90 private AnnotationMetadata getAnnotationMetadataIfServlet(MetadataReader metadataReader,
91 MetadataReaderFactory factory,
92 PathMatchingResourcePatternResolver resourceResolver)
93 {
94 ClassMetadata classMetadata = metadataReader.getClassMetadata();
95
96 try {
97 if (classMetadata.isConcrete() && extendsRemoteServlet(classMetadata, factory, resourceResolver)) {
98 for (String i : metadataReader.getClassMetadata().getInterfaceNames()) {
99 MetadataReader r = getMetadataReader(i, factory, resourceResolver);
100 if (r != null && r.getAnnotationMetadata()
101 .hasAnnotation( RemoteServiceRelativePath.class.getName() )) {
102 return r.getAnnotationMetadata();
103 }
104 }
105 }
106 } catch (IOException e) {
107 getLogger().warn("Failed to read class metadata: " + e);
108 }
109 return null;
110 }
111
112
113
114
115
116
117 public Set<ServletDescriptor> findServlets( String packageName, String startPath, ClassLoader classLoader )
118 throws IOException
119 {
120 Set<ServletDescriptor> servlets = new LinkedHashSet<ServletDescriptor>();
121 PathMatchingResourcePatternResolver pathMatchingResourcePatternResolver = new PathMatchingResourcePatternResolver(
122 classLoader );
123 String patternFinder = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX
124 + ClassUtils.convertClassNameToResourcePath( packageName ) + "/**/*.class";
125
126 Resource[] resources = pathMatchingResourcePatternResolver.getResources( patternFinder );
127 SimpleMetadataReaderFactory simpleMetadataReaderFactory = new SimpleMetadataReaderFactory();
128 getLogger().debug( "springresource " + resources.length + " for pattern " + patternFinder );
129 for ( Resource resource : resources )
130 {
131 getLogger().debug( "springresource " + resource.getFilename() );
132 MetadataReader metadataReader = simpleMetadataReaderFactory.getMetadataReader( resource );
133
134 AnnotationMetadata annotationMetadata = getAnnotationMetadataIfServlet(metadataReader,
135 simpleMetadataReaderFactory,
136 pathMatchingResourcePatternResolver);
137 if ( annotationMetadata != null )
138 {
139 Map<String, Object> annotationAttributes = annotationMetadata
140 .getAnnotationAttributes( RemoteServiceRelativePath.class.getName() );
141 getLogger().debug( "found RemoteServiceRelativePath annotation for class "
142 + metadataReader.getClassMetadata().getClassName() );
143 if ( StringUtils.isNotBlank( startPath ) )
144 {
145 StringBuilder path = new StringBuilder();
146 if ( !startPath.startsWith( "/" ) )
147 {
148 path.append( '/' );
149 }
150 path.append( startPath );
151 String annotationPathValue = (String) annotationAttributes.get( "value" );
152 if ( !annotationPathValue.startsWith( "/" ) )
153 {
154 path.append( '/' );
155 }
156 path.append( annotationPathValue );
157 ServletDescriptor servletDescriptor = new ServletDescriptor( path.toString(), metadataReader
158 .getClassMetadata().getClassName() );
159 servlets.add( servletDescriptor );
160 }
161 else
162 {
163 StringBuilder path = new StringBuilder();
164 String annotationPathValue = (String) annotationAttributes.get( "value" );
165 if ( !annotationPathValue.startsWith( "/" ) )
166 {
167 path.append( '/' );
168 }
169 path.append( annotationPathValue );
170 ServletDescriptor servletDescriptor = new ServletDescriptor( path.toString(), metadataReader
171 .getClassMetadata().getClassName() );
172 servlets.add( servletDescriptor );
173 }
174 }
175 }
176 return servlets;
177 }
178
179 }