001package ball.util.ant.taskdefs; 002/*- 003 * ########################################################################## 004 * Utilities 005 * $Id: TypeTask.java 6118 2020-06-04 19:31:45Z ball $ 006 * $HeadURL: svn+ssh://svn.hcf.dev/var/spool/scm/repository.svn/ball-util/trunk/src/main/java/ball/util/ant/taskdefs/TypeTask.java $ 007 * %% 008 * Copyright (C) 2008 - 2020 Allen D. Ball 009 * %% 010 * Licensed under the Apache License, Version 2.0 (the "License"); 011 * you may not use this file except in compliance with the License. 012 * You may obtain a copy of the License at 013 * 014 * http://www.apache.org/licenses/LICENSE-2.0 015 * 016 * Unless required by applicable law or agreed to in writing, software 017 * distributed under the License is distributed on an "AS IS" BASIS, 018 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 019 * See the License for the specific language governing permissions and 020 * limitations under the License. 021 * ########################################################################## 022 */ 023import ball.beans.PropertyDescriptorsTableModel; 024import ball.lang.reflect.JavaLangReflectMethods; 025import ball.swing.table.SimpleTableModel; 026import java.beans.BeanDescriptor; 027import java.beans.BeanInfo; 028import java.beans.Introspector; 029import java.beans.PropertyDescriptor; 030import java.net.URL; 031import java.util.ArrayList; 032import java.util.stream.Stream; 033import lombok.Getter; 034import lombok.NoArgsConstructor; 035import lombok.Setter; 036import lombok.ToString; 037import lombok.experimental.Accessors; 038import org.apache.commons.lang3.ClassUtils; 039import org.apache.tools.ant.BuildException; 040import org.apache.tools.ant.Task; 041import org.apache.tools.ant.util.ClasspathUtils; 042 043import static lombok.AccessLevel.PROTECTED; 044import static org.apache.commons.lang3.StringUtils.EMPTY; 045 046/** 047 * Abstract {@link.uri http://ant.apache.org/ Ant} {@link Task} to specify a 048 * type ({@link Class}). 049 * 050 * {@ant.task} 051 * 052 * @author {@link.uri mailto:ball@hcf.dev Allen D. Ball} 053 * @version $Revision: 6118 $ 054 */ 055@NoArgsConstructor(access = PROTECTED) 056public abstract class TypeTask extends Task 057 implements AnnotatedAntTask, 058 ClasspathDelegateAntTask, 059 JavaLangReflectMethods { 060 @Getter @Setter @Accessors(chain = true, fluent = true) 061 private ClasspathUtils.Delegate delegate = null; 062 @NotNull @Getter 063 private String type = null; 064 065 public void setType(String string) { 066 type = string; 067 ClasspathDelegateAntTask.super.setClassname(type); 068 } 069 070 @Override 071 public void setClassname(String string) { setType(string); } 072 073 @Override 074 public void init() throws BuildException { 075 super.init(); 076 ClasspathDelegateAntTask.super.init(); 077 } 078 079 @Override 080 public void execute() throws BuildException { 081 super.execute(); 082 AnnotatedAntTask.super.execute(); 083 } 084 085 /** 086 * {@link.uri http://ant.apache.org/ Ant} 087 * {@link org.apache.tools.ant.Task} to display {@link BeanInfo} 088 * for a specified {@link Class}. 089 * 090 * {@ant.task} 091 */ 092 @AntTask("bean-info-for") 093 @NoArgsConstructor @ToString 094 public static class BeanInfoFor extends TypeTask { 095 @Override 096 public void execute() throws BuildException { 097 super.execute(); 098 099 try { 100 log(Introspector.getBeanInfo(getClassForName(getType()))); 101 } catch (BuildException exception) { 102 throw exception; 103 } catch (Throwable throwable) { 104 throwable.printStackTrace(); 105 throw new BuildException(throwable); 106 } 107 } 108 109 private void log(BeanInfo bean) { 110 log(new BeanHeaderTableModel(bean.getBeanDescriptor())); 111 log(); 112 log(new TableModelImpl(bean.getPropertyDescriptors())); 113 log(bean.getAdditionalBeanInfo()); 114 } 115 116 private void log(BeanInfo[] beans) { 117 if (beans != null) { 118 for (BeanInfo bean : beans) { 119 log(); 120 log(bean); 121 } 122 } 123 } 124 125 @ToString 126 private class BeanHeaderTableModel extends SimpleTableModel { 127 private static final long serialVersionUID = -154550807608756372L; 128 129 public BeanHeaderTableModel(BeanDescriptor descriptor) { 130 super(new Object[][] { }, 2); 131 132 row("Bean Class:", 133 descriptor.getBeanClass().getName()); 134 135 if (descriptor.getCustomizerClass() != null) { 136 row("Customizer Class:", 137 descriptor.getCustomizerClass().getName()); 138 } 139 } 140 } 141 142 @ToString 143 private class TableModelImpl extends PropertyDescriptorsTableModel { 144 private static final long serialVersionUID = 3641199494457667293L; 145 146 public TableModelImpl(PropertyDescriptor[] rows) { super(rows); } 147 148 @Override 149 public Object getValueAt(int y, int x) { 150 Object value = super.getValueAt(y, x); 151 152 if (value instanceof Class<?>) { 153 value = ((Class<?>) value).getCanonicalName(); 154 } 155 156 return value; 157 } 158 } 159 } 160 161 /** 162 * {@link.uri http://ant.apache.org/ Ant} 163 * {@link org.apache.tools.ant.Task} to display superclasses of a 164 * specified {@link Class}. 165 * 166 * {@ant.task} 167 */ 168 @AntTask("is-assignable-from") 169 @NoArgsConstructor @ToString 170 public static class IsAssignableFrom extends TypeTask { 171 @NotNull @Getter @Setter 172 private String subtype = null; 173 174 @Override 175 public void execute() throws BuildException { 176 super.execute(); 177 178 try { 179 Class<?> supertype = getClassForName(getType()); 180 Class<?> subtype = getClassForName(getSubtype()); 181 182 log(supertype.getName() + " is " 183 + (supertype.isAssignableFrom(subtype) ? EMPTY : "not ") 184 + "assignable from " + subtype.getName()); 185 } catch (BuildException exception) { 186 throw exception; 187 } catch (Throwable throwable) { 188 throwable.printStackTrace(); 189 throw new BuildException(throwable); 190 } 191 } 192 } 193 194 /** 195 * {@link.uri http://ant.apache.org/ Ant} 196 * {@link org.apache.tools.ant.Task} to display members of a specified 197 * {@link Class}. 198 * 199 * {@ant.task} 200 */ 201 @AntTask("members-of") 202 @NoArgsConstructor @ToString 203 public static class MembersOf extends TypeTask { 204 @Override 205 public void execute() throws BuildException { 206 super.execute(); 207 208 try { 209 Class<?> type = getClassForName(getType()); 210 211 log(type(type)); 212 Stream.of(type.getDeclaredClasses()) 213 .forEach(t -> log(type(t))); 214 Stream.of(type.getDeclaredFields()) 215 .forEach(t -> log(declaration(t))); 216 Stream.of(type.getDeclaredConstructors()) 217 .forEach(t -> log(declaration(t))); 218 Stream.of(type.getDeclaredMethods()) 219 .forEach(t -> log(declaration(t))); 220 } catch (BuildException exception) { 221 throw exception; 222 } catch (Throwable throwable) { 223 throwable.printStackTrace(); 224 throw new BuildException(throwable); 225 } 226 } 227 } 228 229 /** 230 * {@link.uri http://ant.apache.org/ Ant} 231 * {@link org.apache.tools.ant.Task} to display resource path to a 232 * specified {@link Class}. 233 * 234 * {@ant.task} 235 */ 236 @AntTask("resource-path-to") 237 @NoArgsConstructor @ToString 238 public static class ResourcePathTo extends TypeTask { 239 @Override 240 public void execute() throws BuildException { 241 super.execute(); 242 243 try { 244 Class<?> type = getClassForName(getType()); 245 246 log(String.valueOf(type)); 247 248 URL url = 249 type.getClass() 250 .getResource(type.getSimpleName() + ".class"); 251 252 log(String.valueOf(url)); 253 } catch (BuildException exception) { 254 throw exception; 255 } catch (Throwable throwable) { 256 throwable.printStackTrace(); 257 throw new BuildException(throwable); 258 } 259 } 260 } 261 262 /** 263 * {@link.uri http://ant.apache.org/ Ant} 264 * {@link org.apache.tools.ant.Task} to display superclasses of a 265 * specified {@link Class}. 266 * 267 * {@ant.task} 268 */ 269 @AntTask("superclasses-of") 270 @NoArgsConstructor @ToString 271 public static class SuperclassesOf extends TypeTask { 272 @Override 273 public void execute() throws BuildException { 274 super.execute(); 275 276 try { 277 ArrayList<Class<?>> list = new ArrayList<>(); 278 Class<?> type = getClassForName(getType()); 279 280 list.add(type); 281 list.addAll(ClassUtils.getAllSuperclasses(type)); 282 list.addAll(ClassUtils.getAllInterfaces(type)); 283 284 for (Class<?> superclass : list) { 285 log(type(superclass)); 286 } 287 } catch (BuildException exception) { 288 throw exception; 289 } catch (Throwable throwable) { 290 throwable.printStackTrace(); 291 throw new BuildException(throwable); 292 } 293 } 294 } 295}