1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package org.jdtaus.core.container.mojo;
22
23 import java.io.ByteArrayOutputStream;
24 import java.io.File;
25 import java.io.FileInputStream;
26 import java.io.IOException;
27 import java.io.StringWriter;
28 import java.util.Locale;
29 import java.util.zip.GZIPOutputStream;
30 import javax.xml.bind.JAXBException;
31 import org.apache.bcel.classfile.Attribute;
32 import org.apache.bcel.classfile.ClassParser;
33 import org.apache.bcel.classfile.Constant;
34 import org.apache.bcel.classfile.ConstantPool;
35 import org.apache.bcel.classfile.ConstantUtf8;
36 import org.apache.bcel.classfile.JavaClass;
37 import org.apache.bcel.classfile.Unknown;
38 import org.apache.maven.plugin.MojoExecutionException;
39 import org.apache.maven.plugin.MojoFailureException;
40 import org.jdtaus.core.container.ContainerError;
41 import org.jdtaus.core.container.ContextError;
42 import org.jdtaus.core.container.Implementation;
43 import org.jdtaus.core.container.Model;
44 import org.jdtaus.core.container.ModelError;
45 import org.jdtaus.core.container.ModelFactory;
46 import org.jdtaus.core.container.Module;
47 import org.jdtaus.core.container.Specification;
48
49
50
51
52
53
54
55
56
57
58 public class JavaCommitMojo extends JavaContainerMojo
59 {
60
61
62 public JavaCommitMojo()
63 {
64 super();
65 }
66
67 public void execute() throws MojoExecutionException, MojoFailureException
68 {
69 final ClassLoader mavenLoader = Thread.currentThread().
70 getContextClassLoader();
71
72 try
73 {
74 Thread.currentThread().setContextClassLoader(
75 this.getRuntimeClassLoader( mavenLoader ) );
76
77 enableThreadContextClassLoader();
78
79 final Module module = this.getModule();
80 final Model model = ModelFactory.newModel();
81
82 if ( module != null )
83 {
84 for ( int i = module.getSpecifications().size() - 1; i >= 0;
85 i-- )
86 {
87 final Specification spec = module.getSpecifications().
88 getSpecification( i );
89
90 this.commitSpecification(
91 spec, new File( this.getMavenProject().getBuild().
92 getOutputDirectory() ) );
93
94 }
95
96 for ( int i = module.getImplementations().size() - 1; i >= 0;
97 i-- )
98 {
99 final Implementation impl = module.getImplementations().
100 getImplementation( i );
101
102 this.commitImplementation(
103 model, impl, new File( this.getMavenProject().
104 getBuild().getOutputDirectory() ) );
105
106 }
107 }
108 }
109 catch ( final ContextError e )
110 {
111 throw new MojoExecutionException( e.getMessage(), e );
112 }
113 catch ( final ContainerError e )
114 {
115 throw new MojoExecutionException( e.getMessage(), e );
116 }
117 catch ( final ModelError e )
118 {
119 throw new MojoExecutionException( e.getMessage(), e );
120 }
121 catch ( final Exception e )
122 {
123 throw new MojoExecutionException( e.getMessage(), e );
124 }
125 finally
126 {
127 disableThreadContextClassLoader();
128 Thread.currentThread().setContextClassLoader( mavenLoader );
129 }
130
131 }
132
133 protected void commitImplementation( final Model model,
134 final Implementation impl,
135 final File outputDirectory )
136 throws IOException, JAXBException
137 {
138 this.enhanceClass( outputDirectory, impl.getIdentifier(),
139 Module.class.getName(),
140 this.serializeImplementation( model, impl ) );
141
142 }
143
144 protected void commitSpecification( final Specification spec,
145 final File outputDirectory )
146 throws IOException, JAXBException
147 {
148 this.enhanceClass( outputDirectory, spec.getIdentifier(),
149 Specification.class.getName(),
150 this.serializeSpecification( spec ) );
151
152 }
153
154 private byte[] serializeImplementation( final Model model,
155 final Implementation impl )
156 throws IOException, JAXBException
157 {
158 final ByteArrayOutputStream baos = new ByteArrayOutputStream();
159 final GZIPOutputStream out = new GZIPOutputStream( baos );
160
161 this.getModelManager().getContainerMarshaller().marshal(
162 this.getModelManager().getResolvedImplementation( model, impl ),
163 out );
164
165 out.close();
166
167 if ( this.getLog().isDebugEnabled() )
168 {
169 final StringWriter writer = new StringWriter();
170 this.getModelManager().getContainerMarshaller().marshal(
171 this.getModelManager().getResolvedImplementation(
172 model, impl ), writer );
173
174 this.getLog().debug( writer.toString() );
175 }
176
177 return baos.toByteArray();
178 }
179
180 private byte[] serializeSpecification( final Specification spec )
181 throws IOException, JAXBException
182 {
183 final ByteArrayOutputStream baos = new ByteArrayOutputStream();
184 final GZIPOutputStream out = new GZIPOutputStream( baos );
185
186 this.getModelManager().getContainerMarshaller().marshal(
187 this.getModelManager().getSpecification( spec ), out );
188
189 out.close();
190
191 if ( this.getLog().isDebugEnabled() )
192 {
193 final StringWriter writer = new StringWriter();
194 this.getModelManager().getContainerMarshaller().marshal(
195 this.getModelManager().getSpecification( spec ), writer );
196
197 this.getLog().debug( writer.toString() );
198 }
199
200 return baos.toByteArray();
201 }
202
203 private void enhanceClass( final File outputDirectory,
204 final String identifier,
205 final String attributeName,
206 final byte[] meta )
207 throws IOException
208 {
209
210
211
212
213
214
215
216
217
218
219 final String classLocation =
220 identifier.replace( '.', File.separatorChar ) + ".class";
221
222 final File classFile = new File( outputDirectory, classLocation );
223 final long fileLength = classFile.length();
224 final ClassParser parser =
225 new ClassParser( new FileInputStream( classFile ),
226 classFile.getName() );
227
228 final JavaClass clazz = parser.parse();
229 Attribute[] attributes = clazz.getAttributes();
230
231 int attributeIndex = -1;
232 int nameIndex = -1;
233
234 for ( int i = attributes.length - 1; i >= 0; i-- )
235 {
236 final Constant constant = clazz.getConstantPool().
237 getConstant( attributes[i].getNameIndex() );
238
239 if ( constant instanceof ConstantUtf8 )
240 {
241 if ( attributeName.equals(
242 ( (ConstantUtf8) constant ).getBytes() ) )
243 {
244 attributeIndex = i;
245 nameIndex = attributes[i].getNameIndex();
246 }
247 }
248 }
249
250 if ( nameIndex == -1 )
251 {
252 final Constant[] pool = clazz.getConstantPool().getConstantPool();
253 final Constant[] tmp = new Constant[ pool.length + 1 ];
254 System.arraycopy( pool, 0, tmp, 0, pool.length );
255 tmp[pool.length] = new ConstantUtf8( attributeName );
256 nameIndex = pool.length;
257 clazz.setConstantPool( new ConstantPool( tmp ) );
258 }
259
260 final Unknown unknown = new Unknown( nameIndex, meta.length, meta,
261 clazz.getConstantPool() );
262
263 if ( attributeIndex == -1 )
264 {
265 final Attribute[] tmp = new Attribute[ attributes.length + 1 ];
266 System.arraycopy( attributes, 0, tmp, 0, attributes.length );
267 tmp[attributes.length] = unknown;
268 attributeIndex = attributes.length;
269 attributes = tmp;
270 }
271 else
272 {
273 attributes[attributeIndex] = unknown;
274 }
275
276 clazz.setAttributes( attributes );
277 clazz.dump( classFile );
278
279 final Number bytes = new Long( classFile.length() - fileLength );
280
281 this.getLog().info( JavaContainerMojoBundle.getInstance().
282 getCommittedFileMessage( Locale.getDefault(), identifier, bytes ) );
283
284 }
285
286 }