Source Code Cross Referenced for StandardGeneratorContext.java in  » Ajax » GWT » com » google » gwt » dev » shell » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Ajax » GWT » com.google.gwt.dev.shell 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * Copyright 2007 Google Inc.
003:         * 
004:         * Licensed under the Apache License, Version 2.0 (the "License"); you may not
005:         * use this file except in compliance with the License. You may obtain a copy of
006:         * the License at
007:         * 
008:         * http://www.apache.org/licenses/LICENSE-2.0
009:         * 
010:         * Unless required by applicable law or agreed to in writing, software
011:         * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
012:         * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
013:         * License for the specific language governing permissions and limitations under
014:         * the License.
015:         */
016:        package com.google.gwt.dev.shell;
017:
018:        import com.google.gwt.core.ext.GeneratorContext;
019:        import com.google.gwt.core.ext.PropertyOracle;
020:        import com.google.gwt.core.ext.TreeLogger;
021:        import com.google.gwt.core.ext.UnableToCompleteException;
022:        import com.google.gwt.core.ext.typeinfo.CompilationUnitProvider;
023:        import com.google.gwt.core.ext.typeinfo.JClassType;
024:        import com.google.gwt.core.ext.typeinfo.NotFoundException;
025:        import com.google.gwt.core.ext.typeinfo.TypeOracle;
026:        import com.google.gwt.dev.cfg.PublicOracle;
027:        import com.google.gwt.dev.jdt.CacheManager;
028:        import com.google.gwt.dev.jdt.StaticCompilationUnitProvider;
029:        import com.google.gwt.dev.jdt.TypeOracleBuilder;
030:        import com.google.gwt.dev.jdt.URLCompilationUnitProvider;
031:        import com.google.gwt.dev.util.Util;
032:
033:        import java.io.ByteArrayOutputStream;
034:        import java.io.CharArrayWriter;
035:        import java.io.File;
036:        import java.io.OutputStream;
037:        import java.io.PrintWriter;
038:        import java.net.MalformedURLException;
039:        import java.net.URL;
040:        import java.util.ArrayList;
041:        import java.util.HashSet;
042:        import java.util.IdentityHashMap;
043:        import java.util.Iterator;
044:        import java.util.List;
045:        import java.util.Map;
046:        import java.util.Set;
047:
048:        /**
049:         * An abstract implementation of a generator context in terms of a
050:         * {@link com.google.gwt.dev.jdt.MutableCompilationServiceHost}, a
051:         * {@link com.google.gwt.dev.jdt.PropertyOracle}, and a
052:         * {@link com.google.gwt.core.server.typeinfo.TypeOracle}. The generator
053:         * interacts with the mutable source oracle by increasing the available
054:         * compilation units as they are generated.
055:         */
056:        public class StandardGeneratorContext implements  GeneratorContext {
057:
058:            /**
059:             * This compilation unit provider acts as a normal compilation unit provider
060:             * as well as a buffer into which generators can write their source. A
061:             * controller should ensure that source isn't requested until the generator
062:             * has finished writing it.
063:             */
064:            private static class GeneratedCompilationUnitProvider extends
065:                    StaticCompilationUnitProvider {
066:
067:                public CharArrayWriter caw;
068:
069:                public PrintWriter pw;
070:
071:                public char[] source;
072:
073:                public GeneratedCompilationUnitProvider(String packageName,
074:                        String simpleTypeName) {
075:                    super (packageName, simpleTypeName, null);
076:                    caw = new CharArrayWriter();
077:                    pw = new PrintWriter(caw, true);
078:                }
079:
080:                /**
081:                 * Finalizes the source and adds this compilation unit to the host.
082:                 */
083:                public void commit() {
084:                    source = caw.toCharArray();
085:                    pw.close();
086:                    pw = null;
087:                    caw.close();
088:                    caw = null;
089:                }
090:
091:                @Override
092:                public char[] getSource() {
093:                    if (source == null) {
094:                        throw new IllegalStateException("source not committed");
095:                    }
096:                    return source;
097:                }
098:            }
099:
100:            /**
101:             * {@link CompilationUnitProvider} used to represent generated source code
102:             * which is stored on disk. This class is only used if the -gen flag is
103:             * specified.
104:             */
105:            private static final class GeneratedCUP extends
106:                    URLCompilationUnitProvider {
107:                private GeneratedCUP(URL url, String name) {
108:                    super (url, name);
109:                }
110:
111:                @Override
112:                public long getLastModified() throws UnableToCompleteException {
113:                    // Make it seem really old so it won't cause recompiles.
114:                    //
115:                    return 0L;
116:                }
117:
118:                @Override
119:                public boolean isTransient() {
120:                    return true;
121:                }
122:            }
123:
124:            /**
125:             * Manages a resource that is in the process of being created by a generator.
126:             */
127:            private static class PendingResource {
128:
129:                private final ByteArrayOutputStream baos = new ByteArrayOutputStream();
130:                private final String partialPath;
131:                private final File pendingFile;
132:
133:                public PendingResource(File outDir, String partialPath) {
134:                    this .partialPath = partialPath;
135:                    this .pendingFile = new File(outDir, partialPath);
136:                }
137:
138:                public void commit(TreeLogger logger)
139:                        throws UnableToCompleteException {
140:                    logger = logger
141:                            .branch(TreeLogger.TRACE,
142:                                    "Writing generated resource '"
143:                                            + pendingFile.getAbsolutePath()
144:                                            + "'", null);
145:
146:                    Util.writeBytesToFile(logger, pendingFile, baos
147:                            .toByteArray());
148:                }
149:
150:                public File getFile() {
151:                    return pendingFile;
152:                }
153:
154:                public OutputStream getOutputStream() {
155:                    return baos;
156:                }
157:
158:                public String getPartialPath() {
159:                    return partialPath;
160:                }
161:            }
162:
163:            private final CacheManager cacheManager;
164:
165:            private final Set<GeneratedCompilationUnitProvider> committedGeneratedCups = new HashSet<GeneratedCompilationUnitProvider>();
166:
167:            private final File genDir;
168:
169:            private final Set<String> generatedTypeNames = new HashSet<String>();
170:
171:            private final File outDir;
172:
173:            private final Map<OutputStream, PendingResource> pendingResourcesByOutputStream = new IdentityHashMap<OutputStream, PendingResource>();
174:
175:            private final PropertyOracle propOracle;
176:
177:            private final PublicOracle publicOracle;
178:
179:            private final TypeOracle typeOracle;
180:
181:            private final Map<PrintWriter, GeneratedCompilationUnitProvider> uncommittedGeneratedCupsByPrintWriter = new IdentityHashMap<PrintWriter, GeneratedCompilationUnitProvider>();
182:
183:            /**
184:             * Normally, the compiler host would be aware of the same types that are
185:             * available in the supplied type oracle although it isn't strictly required.
186:             */
187:            public StandardGeneratorContext(TypeOracle typeOracle,
188:                    PropertyOracle propOracle, PublicOracle publicOracle,
189:                    File genDir, File outDir, CacheManager cacheManager) {
190:                this .typeOracle = typeOracle;
191:                this .propOracle = propOracle;
192:                this .publicOracle = publicOracle;
193:                this .genDir = genDir;
194:                this .outDir = outDir;
195:                this .cacheManager = cacheManager;
196:            }
197:
198:            /**
199:             * Commits a pending generated type.
200:             */
201:            public final void commit(TreeLogger logger, PrintWriter pw) {
202:                GeneratedCompilationUnitProvider gcup = uncommittedGeneratedCupsByPrintWriter
203:                        .get(pw);
204:                if (gcup != null) {
205:                    gcup.commit();
206:                    uncommittedGeneratedCupsByPrintWriter.remove(pw);
207:                    committedGeneratedCups.add(gcup);
208:                } else {
209:                    logger
210:                            .log(
211:                                    TreeLogger.WARN,
212:                                    "Generator attempted to commit an unknown PrintWriter",
213:                                    null);
214:                }
215:            }
216:
217:            public void commitResource(TreeLogger logger, OutputStream os)
218:                    throws UnableToCompleteException {
219:
220:                // Find the pending resource using its output stream as a key.
221:                PendingResource pendingResource = pendingResourcesByOutputStream
222:                        .get(os);
223:                if (pendingResource != null) {
224:                    // Actually write the bytes to disk.
225:                    pendingResource.commit(logger);
226:                    cacheManager.addGeneratedResource(pendingResource
227:                            .getPartialPath());
228:
229:                    // The resource is now no longer pending, so remove it from the map.
230:                    // If the commit above throws an exception, it's okay to leave the entry
231:                    // in the map because it will be reported later as not having been
232:                    // committed, which is accurate.
233:                    pendingResourcesByOutputStream.remove(os);
234:                } else {
235:                    logger
236:                            .log(
237:                                    TreeLogger.WARN,
238:                                    "Generator attempted to commit an unknown OutputStream",
239:                                    null);
240:                    throw new UnableToCompleteException();
241:                }
242:            }
243:
244:            /**
245:             * Call this whenever generators are known to not be running to clear out
246:             * uncommitted compilation units and to force committed compilation units to
247:             * be parsed and added to the type oracle.
248:             * 
249:             * @return types generated during this object's lifetime
250:             */
251:            public final JClassType[] finish(TreeLogger logger)
252:                    throws UnableToCompleteException {
253:
254:                abortUncommittedResources(logger);
255:
256:                // Process pending generated types.
257:                List<String> genTypeNames = new ArrayList<String>();
258:
259:                try {
260:                    TreeLogger branch;
261:                    if (!committedGeneratedCups.isEmpty()) {
262:                        // Assimilate the new types into the type oracle.
263:                        //
264:                        String msg = "Assimilating generated source";
265:                        branch = logger.branch(TreeLogger.DEBUG, msg, null);
266:
267:                        TreeLogger subBranch = null;
268:                        if (branch.isLoggable(TreeLogger.DEBUG)) {
269:                            subBranch = branch.branch(TreeLogger.DEBUG,
270:                                    "Generated source files...", null);
271:                        }
272:
273:                        assert (cacheManager.getTypeOracle() == typeOracle);
274:                        TypeOracleBuilder builder = new TypeOracleBuilder(
275:                                cacheManager);
276:                        for (Iterator<GeneratedCompilationUnitProvider> iter = committedGeneratedCups
277:                                .iterator(); iter.hasNext();) {
278:                            GeneratedCompilationUnitProvider gcup = iter.next();
279:                            String typeName = gcup.getTypeName();
280:                            String genTypeName = gcup.getPackageName() + "."
281:                                    + typeName;
282:                            genTypeNames.add(genTypeName);
283:                            CompilationUnitProvider cup = writeSource(logger,
284:                                    gcup, typeName);
285:                            builder.addCompilationUnit(cup);
286:                            cacheManager.addGeneratedCup(cup);
287:
288:                            if (subBranch != null) {
289:                                subBranch.log(TreeLogger.DEBUG, cup
290:                                        .getLocation(), null);
291:                            }
292:                        }
293:
294:                        builder.build(branch);
295:                    }
296:
297:                    // Return the generated types.
298:                    JClassType[] genTypes = new JClassType[genTypeNames.size()];
299:                    int next = 0;
300:                    for (Iterator<String> iter = genTypeNames.iterator(); iter
301:                            .hasNext();) {
302:                        String genTypeName = iter.next();
303:                        try {
304:                            genTypes[next++] = typeOracle.getType(genTypeName);
305:                        } catch (NotFoundException e) {
306:                            String msg = "Unable to find recently-generated type '"
307:                                    + genTypeName;
308:                            logger.log(TreeLogger.ERROR, msg, null);
309:                            throw new UnableToCompleteException();
310:                        }
311:                    }
312:                    return genTypes;
313:                } finally {
314:
315:                    // Remind the user if there uncommitted cups.
316:                    if (!uncommittedGeneratedCupsByPrintWriter.isEmpty()) {
317:                        String msg = "For the following type(s), generated source was never committed (did you forget to call commit()?)";
318:                        logger = logger.branch(TreeLogger.WARN, msg, null);
319:
320:                        for (Iterator<GeneratedCompilationUnitProvider> iter = uncommittedGeneratedCupsByPrintWriter
321:                                .values().iterator(); iter.hasNext();) {
322:                            StaticCompilationUnitProvider cup = iter.next();
323:                            String typeName = cup.getPackageName() + "."
324:                                    + cup.getTypeName();
325:                            logger.log(TreeLogger.WARN, typeName, null);
326:                        }
327:                    }
328:
329:                    uncommittedGeneratedCupsByPrintWriter.clear();
330:                    committedGeneratedCups.clear();
331:                    generatedTypeNames.clear();
332:                }
333:            }
334:
335:            public File getOutputDir() {
336:                return outDir;
337:            }
338:
339:            public final PropertyOracle getPropertyOracle() {
340:                return propOracle;
341:            }
342:
343:            public final TypeOracle getTypeOracle() {
344:                return typeOracle;
345:            }
346:
347:            public final PrintWriter tryCreate(TreeLogger logger,
348:                    String packageName, String simpleTypeName) {
349:                String typeName = packageName + "." + simpleTypeName;
350:
351:                // Is type already known to the host?
352:                JClassType existingType = typeOracle.findType(packageName,
353:                        simpleTypeName);
354:                if (existingType != null) {
355:                    logger.log(TreeLogger.DEBUG, "Type '" + typeName
356:                            + "' already exists and will not be re-created ",
357:                            null);
358:                    return null;
359:                }
360:
361:                // Has anybody tried to create this type during this iteration?
362:                if (generatedTypeNames.contains(typeName)) {
363:                    final String msg = "A request to create type '"
364:                            + typeName
365:                            + "' was received while the type itself was being created; this might be a generator or configuration bug";
366:                    logger.log(TreeLogger.WARN, msg, null);
367:                    return null;
368:                }
369:
370:                // The type isn't there, so we can let the caller create it. Remember that
371:                // it is pending so another attempt to create the same type will fail.
372:                GeneratedCompilationUnitProvider gcup = new GeneratedCompilationUnitProvider(
373:                        packageName, simpleTypeName);
374:                uncommittedGeneratedCupsByPrintWriter.put(gcup.pw, gcup);
375:                generatedTypeNames.add(typeName);
376:
377:                return gcup.pw;
378:            }
379:
380:            public OutputStream tryCreateResource(TreeLogger logger,
381:                    String partialPath) throws UnableToCompleteException {
382:
383:                logger = logger.branch(TreeLogger.DEBUG,
384:                        "Preparing pending output resource '" + partialPath
385:                                + "'", null);
386:
387:                // Disallow null or empty names.
388:                if (partialPath == null || partialPath.trim().equals("")) {
389:                    logger.log(TreeLogger.ERROR,
390:                            "The resource name must be a non-empty string",
391:                            null);
392:                    throw new UnableToCompleteException();
393:                }
394:
395:                // Disallow absolute paths.
396:                File f = new File(partialPath);
397:                if (f.isAbsolute()) {
398:                    logger
399:                            .log(
400:                                    TreeLogger.ERROR,
401:                                    "Resource paths are intended to be relative to the compiled output directory and cannot be absolute",
402:                                    null);
403:                    throw new UnableToCompleteException();
404:                }
405:
406:                // Disallow backslashes (to promote consistency in calling code).
407:                if (partialPath.indexOf('\\') >= 0) {
408:                    logger
409:                            .log(
410:                                    TreeLogger.ERROR,
411:                                    "Resource paths must contain forward slashes (not backslashes) to denote subdirectories",
412:                                    null);
413:                    throw new UnableToCompleteException();
414:                }
415:
416:                // Check for public path collision.
417:                if (publicOracle.findPublicFile(partialPath) != null) {
418:                    logger.log(TreeLogger.WARN, "Cannot create resource '"
419:                            + partialPath
420:                            + "' because it already exists on the public path",
421:                            null);
422:                    return null;
423:                }
424:
425:                // See if the file is already committed.
426:                if (cacheManager.hasGeneratedResource(partialPath)) {
427:                    return null;
428:                }
429:
430:                // See if the file is pending.
431:                for (Iterator<PendingResource> iter = pendingResourcesByOutputStream
432:                        .values().iterator(); iter.hasNext();) {
433:                    PendingResource pendingResource = iter.next();
434:                    if (pendingResource.getPartialPath().equals(partialPath)) {
435:                        // It is already pending.
436:                        logger.log(TreeLogger.WARN, "The file '" + partialPath
437:                                + "' is already a pending resource", null);
438:                        return null;
439:                    }
440:                }
441:
442:                // Record that this file is pending.
443:                PendingResource pendingResource = new PendingResource(outDir,
444:                        partialPath);
445:                OutputStream os = pendingResource.getOutputStream();
446:                pendingResourcesByOutputStream.put(os, pendingResource);
447:
448:                return os;
449:            }
450:
451:            private void abortUncommittedResources(TreeLogger logger) {
452:                if (pendingResourcesByOutputStream.isEmpty()) {
453:                    // Nothing to do.
454:                    return;
455:                }
456:
457:                // Warn the user about uncommitted resources.
458:                logger = logger
459:                        .branch(
460:                                TreeLogger.WARN,
461:                                "The following resources will not be created because they were never committed (did you forget to call commit()?)",
462:                                null);
463:
464:                try {
465:                    for (Iterator<PendingResource> iter = pendingResourcesByOutputStream
466:                            .values().iterator(); iter.hasNext();) {
467:                        PendingResource pendingResource = iter.next();
468:                        logger.log(TreeLogger.WARN, pendingResource.getFile()
469:                                .getAbsolutePath(), null);
470:                    }
471:                } finally {
472:                    pendingResourcesByOutputStream.clear();
473:                }
474:            }
475:
476:            /**
477:             * Writes the source of the specified compilation unit to disk if a gen
478:             * directory is specified.
479:             * 
480:             * @param cup the compilation unit whose contents might need to be written
481:             * @param simpleTypeName the fully-qualified type name
482:             * @return a wrapper for the existing cup with a proper location
483:             */
484:            private CompilationUnitProvider writeSource(TreeLogger logger,
485:                    CompilationUnitProvider cup, String simpleTypeName)
486:                    throws UnableToCompleteException {
487:
488:                if (genDir == null) {
489:                    // No place to write it.
490:                    return cup;
491:                }
492:
493:                if (Util.isCompilationUnitOnDisk(cup.getLocation())) {
494:                    // Already on disk.
495:                    return cup;
496:                }
497:
498:                // Let's do write it.
499:                String typeName = cup.getPackageName() + "." + simpleTypeName;
500:                String relativePath = typeName.replace('.', '/') + ".java";
501:                File srcFile = new File(genDir, relativePath);
502:                Util.writeCharsAsFile(logger, srcFile, cup.getSource());
503:
504:                // Update the location of the cup
505:                Throwable caught = null;
506:                try {
507:                    URL fileURL = srcFile.toURI().toURL();
508:                    URLCompilationUnitProvider fileBaseCup = new GeneratedCUP(
509:                            fileURL, cup.getPackageName());
510:                    return fileBaseCup;
511:                } catch (MalformedURLException e) {
512:                    caught = e;
513:                }
514:                logger.log(TreeLogger.ERROR,
515:                        "Internal error: cannot build URL from synthesized file name '"
516:                                + srcFile.getAbsolutePath() + "'", caught);
517:                throw new UnableToCompleteException();
518:            }
519:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.